fixed bug #449107
[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
60 /* this is the down and dirty file with all kinds of
61    kludgy & hacky stuff. This is what it is all about
62    CODE GENERATION for a specific MCU . some of the
63    routines may be reusable, will have to see */
64
65 static char *zero = "#0";
66 static char *one = "#1";
67 static char *spname;
68
69 #define D(x) x
70
71 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
72 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
73
74 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
75 static char *fReturn24[] =
76 {"dpl", "dph", "dpx", "b", "a"};
77 static char *fReturn16[] =
78 {"dpl", "dph", "b", "a"};
79 static char **fReturn = fReturn24;
80 static char *accUse[] =
81 {"a", "b"};
82 static char *javaRet[] = { "r0","r1","r2","r3"};
83 static short rbank = -1;
84
85 static struct
86   {
87     short r0Pushed;
88     short r1Pushed;
89     short accInUse;
90     short bInUse;
91     short inLine;
92     short debugLine;
93     short nRegsSaved;
94     set *sendSet;
95   }
96 _G;
97
98 static void saveRBank (int, iCode *, bool);
99
100 #define RESULTONSTACK(x) \
101                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
102                          IC_RESULT(x)->aop->type == AOP_STK )
103
104 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
105 #define MOVA(x) { char *_mova_tmp = strdup(x); \
106                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
107                  { \
108                     emitcode("mov","a,%s",_mova_tmp); \
109                  } \
110                  free(_mova_tmp); \
111                 }
112 #define CLRC    emitcode("clr","c")
113 #define SETC    emitcode("setb","c")
114
115 // A scratch register which will be used to hold
116 // result bytes from operands in far space via DPTR2.
117 #define DP2_RESULT_REG  "_ap"
118
119 static lineNode *lineHead = NULL;
120 static lineNode *lineCurr = NULL;
121
122 static unsigned char SLMask[] =
123 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
124  0xE0, 0xC0, 0x80, 0x00};
125 static unsigned char SRMask[] =
126 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
127  0x07, 0x03, 0x01, 0x00};
128
129 #define LSB     0
130 #define MSB16   1
131 #define MSB24   2
132 #define MSB32   3
133
134 /*-----------------------------------------------------------------*/
135 /* emitcode - writes the code into a file : for now it is simple    */
136 /*-----------------------------------------------------------------*/
137 static void
138 emitcode (char *inst, char *fmt,...)
139 {
140   va_list ap;
141   char lb[INITIAL_INLINEASM];
142   char *lbp = lb;
143
144   va_start (ap, fmt);
145
146   if (inst && *inst)
147     {
148       if (fmt && *fmt)
149         sprintf (lb, "%s\t", inst);
150       else
151         sprintf (lb, "%s", inst);
152       tvsprintf (lb + (strlen (lb)), fmt, ap);
153     }
154   else
155     tvsprintf (lb, fmt, ap);
156
157   while (isspace (*lbp))
158     lbp++;
159
160   if (lbp && *lbp)
161     lineCurr = (lineCurr ?
162                 connectLine (lineCurr, newLineNode (lb)) :
163                 (lineHead = newLineNode (lb)));
164   lineCurr->isInline = _G.inLine;
165   lineCurr->isDebug = _G.debugLine;
166   va_end (ap);
167 }
168
169 /*-----------------------------------------------------------------*/
170 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
171 /*-----------------------------------------------------------------*/
172 static regs *
173 getFreePtr (iCode * ic, asmop ** aopp, bool result)
174 {
175   bool r0iu = FALSE, r1iu = FALSE;
176   bool r0ou = FALSE, r1ou = FALSE;
177
178   /* the logic: if r0 & r1 used in the instruction
179      then we are in trouble otherwise */
180
181   /* first check if r0 & r1 are used by this
182      instruction, in which case we are in trouble */
183   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
184   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
185   if (r0iu && r1iu) {
186       goto endOfWorld;
187     }
188
189   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
190   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
191
192   /* if no usage of r0 then return it */
193   if (!r0iu && !r0ou)
194     {
195       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
196       (*aopp)->type = AOP_R0;
197
198       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
199     }
200
201   /* if no usage of r1 then return it */
202   if (!r1iu && !r1ou)
203     {
204       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
205       (*aopp)->type = AOP_R1;
206
207       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
208     }
209
210   /* now we know they both have usage */
211   /* if r0 not used in this instruction */
212   if (!r0iu)
213     {
214       /* push it if not already pushed */
215       if (!_G.r0Pushed)
216         {
217           emitcode ("push", "%s",
218                     ds390_regWithIdx (R0_IDX)->dname);
219           _G.r0Pushed++;
220         }
221
222       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
223       (*aopp)->type = AOP_R0;
224
225       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
226     }
227
228   /* if r1 not used then */
229
230   if (!r1iu)
231     {
232       /* push it if not already pushed */
233       if (!_G.r1Pushed)
234         {
235           emitcode ("push", "%s",
236                     ds390_regWithIdx (R1_IDX)->dname);
237           _G.r1Pushed++;
238         }
239
240       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
241       (*aopp)->type = AOP_R1;
242       return ds390_regWithIdx (R1_IDX);
243     }
244
245 endOfWorld:
246   /* I said end of world but not quite end of world yet */
247   /* if this is a result then we can push it on the stack */
248   if (result)
249     {
250       (*aopp)->type = AOP_STK;
251       return NULL;
252     }
253
254   /* other wise this is true end of the world */
255   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
256           "getFreePtr should never reach here");
257   exit (1);
258 }
259
260 /*-----------------------------------------------------------------*/
261 /* newAsmop - creates a new asmOp                                  */
262 /*-----------------------------------------------------------------*/
263 static asmop *
264 newAsmop (short type)
265 {
266   asmop *aop;
267
268   aop = Safe_calloc (1, sizeof (asmop));
269   aop->type = type;
270   return aop;
271 }
272
273 static int _currentDPS;         /* Current processor DPS. */
274 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
275 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
276
277 /*-----------------------------------------------------------------*/
278 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
279 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
280 /* alternate DPTR (DPL1/DPH1/DPX1).          */
281 /*-----------------------------------------------------------------*/
282 static void
283 genSetDPTR (int n)
284 {
285
286   /* If we are doing lazy evaluation, simply note the desired
287    * change, but don't emit any code yet.
288    */
289   if (_lazyDPS)
290     {
291       _desiredDPS = n;
292       return;
293     }
294
295   if (!n)
296     {
297       emitcode ("mov", "dps,#0");
298     }
299   else
300     {
301       TR_DPTR("#1");
302       emitcode ("mov", "dps,#1");
303     }
304 }
305
306 /*-----------------------------------------------------------------*/
307 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
308 /*                   */
309 /* Any code that operates on DPTR (NB: not on the individual     */
310 /* components, like DPH) *must* call _flushLazyDPS() before using  */
311 /* DPTR within a lazy DPS evaluation block.        */
312 /*                   */
313 /* Note that aopPut and aopGet already contain the proper calls to */
314 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
315 /* DPS evaluation block.             */
316 /*                   */
317 /* Also, _flushLazyDPS must be called before any flow control      */
318 /* operations that could potentially branch out of the block.    */
319 /*                         */
320 /* Lazy DPS evaluation is simply an optimization (though an      */
321 /* important one), so if in doubt, leave it out.       */
322 /*-----------------------------------------------------------------*/
323 static void
324 _startLazyDPSEvaluation (void)
325 {
326   _currentDPS = 0;
327   _desiredDPS = 0;
328 #ifdef BETTER_LITERAL_SHIFT  
329   _lazyDPS++;
330 #else
331   _lazyDPS = 1;
332 #endif  
333 }
334
335 /*-----------------------------------------------------------------*/
336 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
337 /* desired one. Call before using DPTR within a lazy DPS evaluation */
338 /* block.                */
339 /*-----------------------------------------------------------------*/
340 static void
341 _flushLazyDPS (void)
342 {
343   if (!_lazyDPS)
344     {
345       /* nothing to do. */
346       return;
347     }
348
349   if (_desiredDPS != _currentDPS)
350     {
351       if (_desiredDPS)
352         {
353           emitcode ("inc", "dps");
354         }
355       else
356         {
357           emitcode ("dec", "dps");
358         }
359       _currentDPS = _desiredDPS;
360     }
361 }
362
363 /*-----------------------------------------------------------------*/
364 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
365 /*                   */
366 /* Forces us back to the safe state (standard DPTR selected).    */
367 /*-----------------------------------------------------------------*/
368 static void
369 _endLazyDPSEvaluation (void)
370 {
371 #ifdef BETTER_LITERAL_SHIFT  
372   _lazyDPS--;
373 #else
374   _lazyDPS = 0;
375 #endif    
376   if (!_lazyDPS)
377   {
378     if (_currentDPS)
379     {
380       genSetDPTR (0);
381       _flushLazyDPS ();
382     }
383     _currentDPS = 0;
384     _desiredDPS = 0;
385   }
386 }
387
388
389
390 /*-----------------------------------------------------------------*/
391 /* pointerCode - returns the code for a pointer type               */
392 /*-----------------------------------------------------------------*/
393 static int
394 pointerCode (sym_link * etype)
395 {
396
397   return PTR_TYPE (SPEC_OCLS (etype));
398
399 }
400
401 /*-----------------------------------------------------------------*/
402 /* aopForSym - for a true symbol                                   */
403 /*-----------------------------------------------------------------*/
404 static asmop *
405 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
406 {
407   asmop *aop;
408   memmap *space = SPEC_OCLS (sym->etype);
409
410   /* if already has one */
411   if (sym->aop)
412     return sym->aop;
413
414   /* assign depending on the storage class */
415   /* if it is on the stack or indirectly addressable */
416   /* space we need to assign either r0 or r1 to it   */
417   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
418     {
419       sym->aop = aop = newAsmop (0);
420       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
421       aop->size = getSize (sym->type);
422
423       /* now assign the address of the variable to
424          the pointer register */
425       if (aop->type != AOP_STK)
426         {
427
428           if (sym->onStack)
429             {
430               if (_G.accInUse)
431                 emitcode ("push", "acc");
432
433               if (_G.bInUse)
434                 emitcode ("push", "b");
435
436               emitcode ("mov", "a,_bp");
437               emitcode ("add", "a,#!constbyte",
438                         ((sym->stack < 0) ?
439                          ((char) (sym->stack - _G.nRegsSaved)) :
440                          ((char) sym->stack)) & 0xff);
441               emitcode ("mov", "%s,a",
442                         aop->aopu.aop_ptr->name);
443
444               if (_G.bInUse)
445                 emitcode ("pop", "b");
446
447               if (_G.accInUse)
448                 emitcode ("pop", "acc");
449             }
450           else
451             emitcode ("mov", "%s,#%s",
452                       aop->aopu.aop_ptr->name,
453                       sym->rname);
454           aop->paged = space->paged;
455         }
456       else
457         aop->aopu.aop_stk = sym->stack;
458       return aop;
459     }
460
461   if (sym->onStack && options.stack10bit)
462     {
463         short stack_val = -((sym->stack < 0) ?
464                             ((short) (sym->stack - _G.nRegsSaved)) :
465                             ((short) sym->stack)) ;
466       /* It's on the 10 bit stack, which is located in
467        * far data space.
468        */
469         if (stack_val < 0 && stack_val > -3) { /* between -3 & -1 */
470             if (useDP2) {
471                 if (options.model == MODEL_FLAT24)
472                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
473                 TR_DPTR("#2");
474                 emitcode ("mov", "dph1,_bpx+1");
475                 emitcode ("mov", "dpl1,_bpx");
476                 emitcode ("mov","dps,#1");
477             } else {
478                 if (options.model == MODEL_FLAT24)
479                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
480                 emitcode ("mov", "dph,_bpx+1");
481                 emitcode ("mov", "dpl,_bpx");
482             }
483             stack_val = -stack_val;
484             while (stack_val--) {
485                 emitcode ("inc","dptr");
486             }
487             if (useDP2) {
488                 emitcode("mov","dps,#0");
489             }
490         }  else {
491             if (_G.accInUse)
492                 emitcode ("push", "acc");
493             
494             if (_G.bInUse)
495                 emitcode ("push", "b");
496         
497             emitcode ("mov", "a,_bpx");
498             emitcode ("clr","c");
499             emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
500             emitcode ("mov","b,a");
501             emitcode ("mov","a,_bpx+1");
502             emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
503             if (useDP2) {
504                 if (options.model == MODEL_FLAT24)
505                     emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
506                 TR_DPTR("#2");
507                 emitcode ("mov", "dph1,a");
508                 emitcode ("mov", "dpl1,b");
509             } else {
510                 if (options.model == MODEL_FLAT24)
511                     emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
512                 emitcode ("mov", "dph,a");
513                 emitcode ("mov", "dpl,b");
514             }
515             
516             if (_G.bInUse)
517                 emitcode ("pop", "b");
518             
519             if (_G.accInUse)
520                 emitcode ("pop", "acc");
521         }
522         sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
523         aop->size = getSize (sym->type);
524         return aop;
525     }
526
527   /* if in bit space */
528   if (IN_BITSPACE (space))
529     {
530       sym->aop = aop = newAsmop (AOP_CRY);
531       aop->aopu.aop_dir = sym->rname;
532       aop->size = getSize (sym->type);
533       return aop;
534     }
535   /* if it is in direct space */
536   if (IN_DIRSPACE (space))
537     {
538       sym->aop = aop = newAsmop (AOP_DIR);
539       aop->aopu.aop_dir = sym->rname;
540       aop->size = getSize (sym->type);
541       return aop;
542     }
543
544   /* special case for a function */
545   if (IS_FUNC (sym->type))
546     {
547       sym->aop = aop = newAsmop (AOP_IMMD);
548       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
549       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
550       aop->size = FPTRSIZE;
551       return aop;
552     }
553
554   /* only remaining is far space */
555   /* in which case DPTR gets the address */
556   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
557   if (useDP2)
558     {
559       genSetDPTR (1);
560       _flushLazyDPS ();
561       emitcode ("mov", "dptr,#%s", sym->rname);
562       genSetDPTR (0);
563     }
564   else
565     {
566       emitcode ("mov", "dptr,#%s", sym->rname);
567     }
568   aop->size = getSize (sym->type);
569
570   /* if it is in code space */
571   if (IN_CODESPACE (space))
572     aop->code = 1;
573
574   return aop;
575 }
576
577 /*-----------------------------------------------------------------*/
578 /* aopForRemat - rematerialzes an object                           */
579 /*-----------------------------------------------------------------*/
580 static asmop *
581 aopForRemat (symbol * sym)
582 {
583   iCode *ic = sym->rematiCode;
584   asmop *aop = newAsmop (AOP_IMMD);
585   int ptr_type =0;
586   int val = 0;
587
588   for (;;)
589     {
590       if (ic->op == '+')
591         val += (int) operandLitValue (IC_RIGHT (ic));
592       else if (ic->op == '-')
593         val -= (int) operandLitValue (IC_RIGHT (ic));
594       else if (IS_CAST_ICODE(ic)) {
595               sym_link *from_type = operandType(IC_RIGHT(ic));
596               aop->aopu.aop_immd.from_cast_remat = 1;
597               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
598               ptr_type = DCL_TYPE(from_type);
599               if (ptr_type == IPOINTER) {
600                 // bug #481053
601                 ptr_type = POINTER;
602               }
603               continue ;
604       } else break;
605       
606       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
607     }
608
609   if (val)
610     sprintf (buffer, "(%s %c 0x%04x)",
611              OP_SYMBOL (IC_LEFT (ic))->rname,
612              val >= 0 ? '+' : '-',
613              abs (val) & 0xffff);
614   else
615     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
616
617   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
618   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
619   /* set immd2 field if required */
620   if (aop->aopu.aop_immd.from_cast_remat) {
621           tsprintf(buffer,"#!constbyte",ptr_type);
622           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
623           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
624   }
625
626   return aop;
627 }
628
629 /*-----------------------------------------------------------------*/
630 /* aopHasRegs - returns true if aop has regs between from-to       */
631 /*-----------------------------------------------------------------*/
632 static int aopHasRegs(asmop *aop, int from, int to)
633 {
634     int size =0;
635
636     if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
637
638     for (; size < aop->size ; size++) {
639         int reg;
640         for (reg = from ; reg <= to ; reg++)
641             if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
642     }
643     return 0;
644 }
645
646 /*-----------------------------------------------------------------*/
647 /* regsInCommon - two operands have some registers in common       */
648 /*-----------------------------------------------------------------*/
649 static bool
650 regsInCommon (operand * op1, operand * op2)
651 {
652   symbol *sym1, *sym2;
653   int i;
654
655   /* if they have registers in common */
656   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
657     return FALSE;
658
659   sym1 = OP_SYMBOL (op1);
660   sym2 = OP_SYMBOL (op2);
661
662   if (sym1->nRegs == 0 || sym2->nRegs == 0)
663     return FALSE;
664
665   for (i = 0; i < sym1->nRegs; i++)
666     {
667       int j;
668       if (!sym1->regs[i])
669         continue;
670
671       for (j = 0; j < sym2->nRegs; j++)
672         {
673           if (!sym2->regs[j])
674             continue;
675
676           if (sym2->regs[j] == sym1->regs[i])
677             return TRUE;
678         }
679     }
680
681   return FALSE;
682 }
683
684 /*-----------------------------------------------------------------*/
685 /* operandsEqu - equivalent                                        */
686 /*-----------------------------------------------------------------*/
687 static bool
688 operandsEqu (operand * op1, operand * op2)
689 {
690   symbol *sym1, *sym2;
691
692   /* if they not symbols */
693   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
694     return FALSE;
695
696   sym1 = OP_SYMBOL (op1);
697   sym2 = OP_SYMBOL (op2);
698
699   /* if both are itemps & one is spilt
700      and the other is not then false */
701   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
702       sym1->isspilt != sym2->isspilt)
703     return FALSE;
704
705   /* if they are the same */
706   if (sym1 == sym2)
707     return TRUE;
708
709   if (strcmp (sym1->rname, sym2->rname) == 0)
710     return TRUE;
711
712
713   /* if left is a tmp & right is not */
714   if (IS_ITEMP (op1) &&
715       !IS_ITEMP (op2) &&
716       sym1->isspilt &&
717       (sym1->usl.spillLoc == sym2))
718     return TRUE;
719
720   if (IS_ITEMP (op2) &&
721       !IS_ITEMP (op1) &&
722       sym2->isspilt &&
723       sym1->level > 0 &&
724       (sym2->usl.spillLoc == sym1))
725     return TRUE;
726
727   return FALSE;
728 }
729
730 /*-----------------------------------------------------------------*/
731 /* sameRegs - two asmops have the same registers                   */
732 /*-----------------------------------------------------------------*/
733 static bool
734 sameRegs (asmop * aop1, asmop * aop2)
735 {
736   int i;
737
738   if (aop1 == aop2)
739     {
740       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
741         {
742           return FALSE;
743         }
744       return TRUE;
745     }
746
747   if (aop1->type != AOP_REG ||
748       aop2->type != AOP_REG)
749     return FALSE;
750
751   if (aop1->size != aop2->size)
752     return FALSE;
753
754   for (i = 0; i < aop1->size; i++)
755     if (aop1->aopu.aop_reg[i] !=
756         aop2->aopu.aop_reg[i])
757       return FALSE;
758
759   return TRUE;
760 }
761
762 /*-----------------------------------------------------------------*/
763 /* aopOp - allocates an asmop for an operand  :                    */
764 /*-----------------------------------------------------------------*/
765 static void
766 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
767 {
768   asmop *aop;
769   symbol *sym;
770   int i;
771
772   if (!op)
773     return;
774
775   /* if this a literal */
776   if (IS_OP_LITERAL (op))
777     {
778       op->aop = aop = newAsmop (AOP_LIT);
779       aop->aopu.aop_lit = op->operand.valOperand;
780       aop->size = getSize (operandType (op));
781       return;
782     }
783
784   /* if already has a asmop then continue */
785   if (op->aop)
786     return;
787
788   /* if the underlying symbol has a aop */
789   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
790     {
791       op->aop = OP_SYMBOL (op)->aop;
792       return;
793     }
794
795   /* if this is a true symbol */
796   if (IS_TRUE_SYMOP (op))
797     {
798       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
799       return;
800     }
801
802   /* this is a temporary : this has
803      only four choices :
804      a) register
805      b) spillocation
806      c) rematerialize
807      d) conditional
808      e) can be a return use only */
809
810   sym = OP_SYMBOL (op);
811
812
813   /* if the type is a conditional */
814   if (sym->regType == REG_CND)
815     {
816       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
817       aop->size = 0;
818       return;
819     }
820
821   /* if it is spilt then two situations
822      a) is rematerialize
823      b) has a spill location */
824   if (sym->isspilt || sym->nRegs == 0)
825     {
826
827       /* rematerialize it NOW */
828       if (sym->remat)
829         {
830           sym->aop = op->aop = aop =
831             aopForRemat (sym);
832           aop->size = getSize (sym->type);
833           return;
834         }
835
836       if (sym->accuse)
837         {
838           int i;
839           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
840           aop->size = getSize (sym->type);
841           for (i = 0; i < 2; i++)
842             aop->aopu.aop_str[i] = accUse[i];
843           return;
844         }
845
846       if (sym->ruonly)
847         {
848           int i;
849
850           if (useDP2)
851             {
852               /* a AOP_STR uses DPTR, but DPTR is already in use;
853                * we're just hosed.
854                */
855               fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name);
856             }
857
858           aop = op->aop = sym->aop = newAsmop (AOP_STR);
859           aop->size = getSize (sym->type);
860           for (i = 0; i < (int) fReturnSizeDS390; i++)
861             aop->aopu.aop_str[i] = fReturn[i];
862           return;
863         }
864
865       /* else spill location  */
866       if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
867           /* force a new aop if sizes differ */
868           sym->usl.spillLoc->aop = NULL;
869       }
870       sym->aop = op->aop = aop =
871         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
872       aop->size = getSize (sym->type);
873       return;
874     }
875
876   /* must be in a register */
877   sym->aop = op->aop = aop = newAsmop (AOP_REG);
878   aop->size = sym->nRegs;
879   for (i = 0; i < sym->nRegs; i++)
880     aop->aopu.aop_reg[i] = sym->regs[i];
881 }
882
883 /*-----------------------------------------------------------------*/
884 /* freeAsmop - free up the asmop given to an operand               */
885 /*----------------------------------------------------------------*/
886 static void
887 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
888 {
889   asmop *aop;
890
891   if (!op)
892     aop = aaop;
893   else
894     aop = op->aop;
895
896   if (!aop)
897     return;
898
899   if (aop->freed)
900     goto dealloc;
901
902   aop->freed = 1;
903
904   /* depending on the asmop type only three cases need work AOP_RO
905      , AOP_R1 && AOP_STK */
906   switch (aop->type)
907     {
908     case AOP_R0:
909       if (_G.r0Pushed)
910         {
911           if (pop)
912             {
913               emitcode ("pop", "ar0");
914               _G.r0Pushed--;
915             }
916         }
917       bitVectUnSetBit (ic->rUsed, R0_IDX);
918       break;
919
920     case AOP_R1:
921       if (_G.r1Pushed)
922         {
923           if (pop)
924             {
925               emitcode ("pop", "ar1");
926               _G.r1Pushed--;
927             }
928         }
929       bitVectUnSetBit (ic->rUsed, R1_IDX);
930       break;
931
932     case AOP_STK:
933       {
934         int sz = aop->size;
935         int stk = aop->aopu.aop_stk + aop->size;
936         bitVectUnSetBit (ic->rUsed, R0_IDX);
937         bitVectUnSetBit (ic->rUsed, R1_IDX);
938
939         getFreePtr (ic, &aop, FALSE);
940
941         if (options.stack10bit)
942           {
943             /* I'm not sure what to do here yet... */
944             /* #STUB */
945             fprintf (stderr,
946                      "*** Warning: probably generating bad code for "
947                      "10 bit stack mode.\n");
948           }
949
950         if (stk)
951           {
952             emitcode ("mov", "a,_bp");
953             emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
954             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
955           }
956         else
957           {
958             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
959           }
960
961         while (sz--)
962           {
963             emitcode ("pop", "acc");
964             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
965             if (!sz)
966               break;
967             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
968           }
969         op->aop = aop;
970         freeAsmop (op, NULL, ic, TRUE);
971         if (_G.r0Pushed)
972           {
973             emitcode ("pop", "ar0");
974             _G.r0Pushed--;
975           }
976
977         if (_G.r1Pushed)
978           {
979             emitcode ("pop", "ar1");
980             _G.r1Pushed--;
981           }
982       }
983     }
984
985 dealloc:
986   /* all other cases just dealloc */
987   if (op)
988     {
989       op->aop = NULL;
990       if (IS_SYMOP (op))
991         {
992           OP_SYMBOL (op)->aop = NULL;
993           /* if the symbol has a spill */
994           if (SPIL_LOC (op))
995             SPIL_LOC (op)->aop = NULL;
996         }
997     }
998 }
999
1000 /*------------------------------------------------------------------*/
1001 /* aopGet - for fetching value of the aop                           */
1002 /*                    */
1003 /* Set canClobberACC if you are sure it is OK to clobber the value  */
1004 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
1005 /* just less efficient.               */
1006 /*------------------------------------------------------------------*/
1007
1008 static char *
1009 aopGet (asmop * aop,
1010         int offset,
1011         bool bit16,
1012         bool dname,
1013         bool canClobberACC)
1014 {
1015   char *s = buffer;
1016   char *rs;
1017
1018   /* offset is greater than
1019      size then zero */
1020   if (offset > (aop->size - 1) &&
1021       aop->type != AOP_LIT)
1022     return zero;
1023
1024   /* depending on type */
1025   switch (aop->type)
1026     {
1027
1028     case AOP_R0:
1029     case AOP_R1:
1030       /* if we need to increment it */
1031       while (offset > aop->coff)
1032         {
1033           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1034           aop->coff++;
1035         }
1036
1037       while (offset < aop->coff)
1038         {
1039           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1040           aop->coff--;
1041         }
1042
1043       aop->coff = offset;
1044       if (aop->paged)
1045         {
1046           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1047           return (dname ? "acc" : "a");
1048         }
1049       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1050       rs = Safe_calloc (1, strlen (s) + 1);
1051       strcpy (rs, s);
1052       return rs;
1053
1054     case AOP_DPTR:
1055     case AOP_DPTR2:
1056
1057       if (aop->type == AOP_DPTR2)
1058         {
1059           genSetDPTR (1);
1060           if (!canClobberACC)
1061             {
1062                     TR_AP("#1");
1063                     emitcode ("xch", "a, %s", DP2_RESULT_REG);
1064             }
1065         }
1066
1067       _flushLazyDPS ();
1068
1069       while (offset > aop->coff)
1070         {
1071           emitcode ("inc", "dptr");
1072           aop->coff++;
1073         }
1074
1075       while (offset < aop->coff)
1076         {
1077           emitcode ("lcall", "__decdptr");
1078           aop->coff--;
1079         }
1080
1081       aop->coff = offset;
1082       if (aop->code)
1083         {
1084           emitcode ("clr", "a");
1085           emitcode ("movc", "a,@a+dptr");
1086         }
1087       else
1088         {
1089           emitcode ("movx", "a,@dptr");
1090         }
1091
1092       if (aop->type == AOP_DPTR2)
1093         {
1094           genSetDPTR (0);
1095           if (!canClobberACC)
1096             {
1097        TR_AP("#2");
1098               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1099               return DP2_RESULT_REG;
1100             }
1101         }
1102       return (dname ? "acc" : "a");
1103
1104     case AOP_IMMD:
1105       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1106               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1107       } else if (bit16)
1108         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1109       else if (offset) {
1110           switch (offset) {
1111           case 1:
1112               tsprintf(s,"#!his",aop->aopu.aop_immd.aop_immd1);
1113               break;
1114           case 2:
1115               tsprintf(s,"#!hihis",aop->aopu.aop_immd.aop_immd1);
1116               break;
1117           case 3:
1118               tsprintf(s,"#!hihihis",aop->aopu.aop_immd.aop_immd1);
1119               break;
1120           default: /* should not need this (just in case) */
1121               sprintf (s, "#(%s >> %d)",
1122                        aop->aopu.aop_immd.aop_immd1,
1123                        offset * 8);
1124           }
1125       }
1126       else
1127         sprintf (s, "#%s",
1128                  aop->aopu.aop_immd.aop_immd1);
1129       rs = Safe_calloc (1, strlen (s) + 1);
1130       strcpy (rs, s);
1131       return rs;
1132
1133     case AOP_DIR:
1134       if (offset)
1135         sprintf (s, "(%s + %d)",
1136                  aop->aopu.aop_dir,
1137                  offset);
1138       else
1139         sprintf (s, "%s", aop->aopu.aop_dir);
1140       rs = Safe_calloc (1, strlen (s) + 1);
1141       strcpy (rs, s);
1142       return rs;
1143
1144     case AOP_REG:
1145       if (dname)
1146         return aop->aopu.aop_reg[offset]->dname;
1147       else
1148         return aop->aopu.aop_reg[offset]->name;
1149
1150     case AOP_CRY:
1151       emitcode ("clr", "a");
1152       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1153       emitcode ("rlc", "a");
1154       return (dname ? "acc" : "a");
1155
1156     case AOP_ACC:
1157       if (!offset && dname)
1158         return "acc";
1159       return aop->aopu.aop_str[offset];
1160
1161     case AOP_LIT:
1162       return aopLiteral (aop->aopu.aop_lit, offset);
1163
1164     case AOP_STR:
1165       aop->coff = offset;
1166       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1167           dname)
1168         return "acc";
1169
1170       return aop->aopu.aop_str[offset];
1171
1172     }
1173
1174   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1175           "aopget got unsupported aop->type");
1176   exit (1);
1177 }
1178 /*-----------------------------------------------------------------*/
1179 /* aopPut - puts a string for a aop                                */
1180 /*-----------------------------------------------------------------*/
1181 static void
1182 aopPut (asmop * aop, char *s, int offset)
1183 {
1184   char *d = buffer;
1185
1186   if (aop->size && offset > (aop->size - 1))
1187     {
1188       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1189               "aopPut got offset > aop->size");
1190       exit (1);
1191     }
1192
1193   /* will assign value to value */
1194   /* depending on where it is ofcourse */
1195   switch (aop->type)
1196     {
1197     case AOP_DIR:
1198       if (offset)
1199         sprintf (d, "(%s + %d)",
1200                  aop->aopu.aop_dir, offset);
1201       else
1202         sprintf (d, "%s", aop->aopu.aop_dir);
1203
1204       if (strcmp (d, s))
1205         emitcode ("mov", "%s,%s", d, s);
1206
1207       break;
1208
1209     case AOP_REG:
1210       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1211           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1212         {
1213           if (*s == '@' ||
1214               strcmp (s, "r0") == 0 ||
1215               strcmp (s, "r1") == 0 ||
1216               strcmp (s, "r2") == 0 ||
1217               strcmp (s, "r3") == 0 ||
1218               strcmp (s, "r4") == 0 ||
1219               strcmp (s, "r5") == 0 ||
1220               strcmp (s, "r6") == 0 ||
1221               strcmp (s, "r7") == 0)
1222             emitcode ("mov", "%s,%s",
1223                       aop->aopu.aop_reg[offset]->dname, s);
1224           else
1225             emitcode ("mov", "%s,%s",
1226                       aop->aopu.aop_reg[offset]->name, s);
1227         }
1228       break;
1229
1230     case AOP_DPTR:
1231     case AOP_DPTR2:
1232
1233       if (aop->type == AOP_DPTR2)
1234         {
1235           genSetDPTR (1);
1236         }
1237       _flushLazyDPS ();
1238
1239       if (aop->code)
1240         {
1241           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1242                   "aopPut writting to code space");
1243           exit (1);
1244         }
1245
1246       while (offset > aop->coff)
1247         {
1248           aop->coff++;
1249           emitcode ("inc", "dptr");
1250         }
1251
1252       while (offset < aop->coff)
1253         {
1254           aop->coff--;
1255           emitcode ("lcall", "__decdptr");
1256         }
1257
1258       aop->coff = offset;
1259
1260       /* if not in accumulater */
1261       MOVA (s);
1262
1263       emitcode ("movx", "@dptr,a");
1264
1265       if (aop->type == AOP_DPTR2)
1266         {
1267           genSetDPTR (0);
1268         }
1269       break;
1270
1271     case AOP_R0:
1272     case AOP_R1:
1273       while (offset > aop->coff)
1274         {
1275           aop->coff++;
1276           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1277         }
1278       while (offset < aop->coff)
1279         {
1280           aop->coff--;
1281           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1282         }
1283       aop->coff = offset;
1284
1285       if (aop->paged)
1286         {
1287           MOVA (s);
1288           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1289
1290         }
1291       else if (*s == '@')
1292         {
1293           MOVA (s);
1294           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1295         }
1296       else if (strcmp (s, "r0") == 0 ||
1297                strcmp (s, "r1") == 0 ||
1298                strcmp (s, "r2") == 0 ||
1299                strcmp (s, "r3") == 0 ||
1300                strcmp (s, "r4") == 0 ||
1301                strcmp (s, "r5") == 0 ||
1302                strcmp (s, "r6") == 0 ||
1303                strcmp (s, "r7") == 0)
1304         {
1305           char buffer[10];
1306           sprintf (buffer, "a%s", s);
1307           emitcode ("mov", "@%s,%s",
1308                     aop->aopu.aop_ptr->name, buffer);
1309         }
1310       else
1311         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1312
1313       break;
1314
1315     case AOP_STK:
1316       if (strcmp (s, "a") == 0)
1317         emitcode ("push", "acc");
1318       else
1319         if (*s=='@') {
1320           MOVA(s);
1321           emitcode ("push", "acc");
1322         } else {
1323           emitcode ("push", s);
1324         }
1325
1326       break;
1327
1328     case AOP_CRY:
1329       /* if bit variable */
1330       if (!aop->aopu.aop_dir)
1331         {
1332           emitcode ("clr", "a");
1333           emitcode ("rlc", "a");
1334         }
1335       else
1336         {
1337           if (s == zero)
1338             emitcode ("clr", "%s", aop->aopu.aop_dir);
1339           else if (s == one)
1340             emitcode ("setb", "%s", aop->aopu.aop_dir);
1341           else if (!strcmp (s, "c"))
1342             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1343           else
1344             {
1345               if (strcmp (s, "a"))
1346                 {
1347                   MOVA (s);
1348                 }
1349               {
1350                 symbol *lbl = newiTempLabel (NULL);
1351                 emitcode ("clr", "c");
1352                 emitcode ("jz", "!tlabel", lbl->key + 100);
1353                 emitcode ("cpl", "c");
1354                 emitcode ("", "!tlabeldef", lbl->key + 100);
1355                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1356               }
1357             }
1358         }
1359       break;
1360
1361     case AOP_STR:
1362       aop->coff = offset;
1363       if (strcmp (aop->aopu.aop_str[offset], s))
1364         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1365       break;
1366
1367     case AOP_ACC:
1368       aop->coff = offset;
1369       if (!offset && (strcmp (s, "acc") == 0))
1370         break;
1371
1372       if (strcmp (aop->aopu.aop_str[offset], s))
1373         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1374       break;
1375
1376     default:
1377       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1378               "aopPut got unsupported aop->type");
1379       exit (1);
1380     }
1381
1382 }
1383
1384
1385 /*--------------------------------------------------------------------*/
1386 /* reAdjustPreg - points a register back to where it should (coff==0) */
1387 /*--------------------------------------------------------------------*/
1388 static void
1389 reAdjustPreg (asmop * aop)
1390 {
1391   if ((aop->coff==0) || (aop->size <= 1)) {
1392     return;
1393   }
1394
1395   switch (aop->type)
1396     {
1397     case AOP_R0:
1398     case AOP_R1:
1399       while (aop->coff--)
1400         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1401       break;
1402     case AOP_DPTR:
1403     case AOP_DPTR2:
1404       if (aop->type == AOP_DPTR2)
1405         {
1406           genSetDPTR (1);
1407           _flushLazyDPS ();
1408         }
1409       while (aop->coff--)
1410         {
1411           emitcode ("lcall", "__decdptr");
1412         }
1413
1414       if (aop->type == AOP_DPTR2)
1415         {
1416           genSetDPTR (0);
1417         }
1418       break;
1419
1420     }
1421   aop->coff=0;
1422 }
1423
1424 #define AOP(op) op->aop
1425 #define AOP_TYPE(op) AOP(op)->type
1426 #define AOP_SIZE(op) AOP(op)->size
1427 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1428                        AOP_TYPE(x) == AOP_R0))
1429
1430 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1431                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1432                          AOP(x)->paged))
1433
1434 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1435                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1436                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1437
1438 /* Workaround for DS80C390 bug: div ab may return bogus results
1439  * if A is accessed in instruction immediately before the div.
1440  *
1441  * Will be fixed in B4 rev of processor, Dallas claims.
1442  */
1443
1444 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1445     if (!AOP_NEEDSACC(RIGHT))         \
1446     {               \
1447       /* We can load A first, then B, since     \
1448        * B (the RIGHT operand) won't clobber A,   \
1449        * thus avoiding touching A right before the div. \
1450        */             \
1451       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1452       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1453       MOVA(L);            \
1454       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1455     }               \
1456     else              \
1457     {               \
1458       /* Just stuff in a nop after loading A. */    \
1459       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1460       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1461       MOVA(L);            \
1462       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1463     }
1464
1465 /*-----------------------------------------------------------------*/
1466 /* genNotFloat - generates not for float operations              */
1467 /*-----------------------------------------------------------------*/
1468 static void
1469 genNotFloat (operand * op, operand * res)
1470 {
1471   int size, offset;
1472   char *l;
1473   symbol *tlbl;
1474
1475   D (emitcode (";", "genNotFloat ");
1476     );
1477
1478   /* we will put 127 in the first byte of
1479      the result */
1480   aopPut (AOP (res), "#127", 0);
1481   size = AOP_SIZE (op) - 1;
1482   offset = 1;
1483
1484   _startLazyDPSEvaluation ();
1485   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1486   MOVA (l);
1487
1488   while (size--)
1489     {
1490       emitcode ("orl", "a,%s",
1491                 aopGet (op->aop,
1492                         offset++, FALSE, FALSE, FALSE));
1493     }
1494   _endLazyDPSEvaluation ();
1495
1496   tlbl = newiTempLabel (NULL);
1497   aopPut (res->aop, one, 1);
1498   emitcode ("jz", "!tlabel", (tlbl->key + 100));
1499   aopPut (res->aop, zero, 1);
1500   emitcode ("", "!tlabeldef", (tlbl->key + 100));
1501
1502   size = res->aop->size - 2;
1503   offset = 2;
1504   /* put zeros in the rest */
1505   while (size--)
1506     aopPut (res->aop, zero, offset++);
1507 }
1508
1509 /*-----------------------------------------------------------------*/
1510 /* opIsGptr: returns non-zero if the passed operand is       */
1511 /* a generic pointer type.             */
1512 /*-----------------------------------------------------------------*/
1513 static int
1514 opIsGptr (operand * op)
1515 {
1516   sym_link *type = operandType (op);
1517
1518   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1519     {
1520       return 1;
1521     }
1522   return 0;
1523 }
1524
1525 /*-----------------------------------------------------------------*/
1526 /* getDataSize - get the operand data size                         */
1527 /*-----------------------------------------------------------------*/
1528 static int
1529 getDataSize (operand * op)
1530 {
1531   int size;
1532   size = AOP_SIZE (op);
1533   if (size == GPTRSIZE)
1534     {
1535       sym_link *type = operandType (op);
1536       if (IS_GENPTR (type))
1537         {
1538           /* generic pointer; arithmetic operations
1539            * should ignore the high byte (pointer type).
1540            */
1541           size--;
1542         }
1543     }
1544   return size;
1545 }
1546
1547 /*-----------------------------------------------------------------*/
1548 /* outAcc - output Acc                                             */
1549 /*-----------------------------------------------------------------*/
1550 static void
1551 outAcc (operand * result)
1552 {
1553   int size, offset;
1554   size = getDataSize (result);
1555   if (size)
1556     {
1557       aopPut (AOP (result), "a", 0);
1558       size--;
1559       offset = 1;
1560       /* unsigned or positive */
1561       while (size--)
1562         {
1563           aopPut (AOP (result), zero, offset++);
1564         }
1565     }
1566 }
1567
1568 /*-----------------------------------------------------------------*/
1569 /* outBitC - output a bit C                                        */
1570 /*-----------------------------------------------------------------*/
1571 static void
1572 outBitC (operand * result)
1573 {
1574   /* if the result is bit */
1575   if (AOP_TYPE (result) == AOP_CRY)
1576     {
1577       aopPut (AOP (result), "c", 0);
1578     }
1579   else
1580     {
1581       emitcode ("clr", "a");
1582       emitcode ("rlc", "a");
1583       outAcc (result);
1584     }
1585 }
1586
1587 /*-----------------------------------------------------------------*/
1588 /* toBoolean - emit code for orl a,operator(sizeop)                */
1589 /*-----------------------------------------------------------------*/
1590 static void
1591 toBoolean (operand * oper)
1592 {
1593   int   size = AOP_SIZE (oper) - 1;
1594   int   offset = 1;
1595   bool usedB = FALSE;
1596
1597   /* The generic part of a generic pointer should
1598    * not participate in it's truth value.
1599    *
1600    * i.e. 0x10000000 is zero.
1601    */
1602   if (opIsGptr (oper))
1603     {
1604       D (emitcode (";", "toBoolean: generic ptr special case.");
1605         );
1606       size--;
1607     }
1608
1609   _startLazyDPSEvaluation ();
1610   if (AOP_NEEDSACC (oper) && size)
1611     {
1612       usedB = TRUE;
1613       emitcode ("push", "b");
1614       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1615     }
1616   else
1617     {
1618       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1619     }
1620   while (size--)
1621     {
1622       if (usedB)
1623         {
1624           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1625         }
1626       else
1627         {
1628           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1629         }
1630     }
1631   _endLazyDPSEvaluation ();
1632
1633   if (usedB)
1634     {
1635       emitcode ("mov", "a,b");
1636       emitcode ("pop", "b");
1637     }
1638 }
1639
1640
1641 /*-----------------------------------------------------------------*/
1642 /* genNot - generate code for ! operation                          */
1643 /*-----------------------------------------------------------------*/
1644 static void
1645 genNot (iCode * ic)
1646 {
1647   symbol *tlbl;
1648   sym_link *optype = operandType (IC_LEFT (ic));
1649
1650   D (emitcode (";", "genNot ");
1651     );
1652
1653   /* assign asmOps to operand & result */
1654   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1655   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1656
1657   /* if in bit space then a special case */
1658   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1659     {
1660       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1661       emitcode ("cpl", "c");
1662       outBitC (IC_RESULT (ic));
1663       goto release;
1664     }
1665
1666   /* if type float then do float */
1667   if (IS_FLOAT (optype))
1668     {
1669       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1670       goto release;
1671     }
1672
1673   toBoolean (IC_LEFT (ic));
1674
1675   tlbl = newiTempLabel (NULL);
1676   emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1677   emitcode ("", "!tlabeldef", tlbl->key + 100);
1678   outBitC (IC_RESULT (ic));
1679
1680 release:
1681   /* release the aops */
1682   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1683   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1684 }
1685
1686
1687 /*-----------------------------------------------------------------*/
1688 /* genCpl - generate code for complement                           */
1689 /*-----------------------------------------------------------------*/
1690 static void
1691 genCpl (iCode * ic)
1692 {
1693   int offset = 0;
1694   int size;
1695   symbol *tlbl;
1696
1697   D (emitcode (";", "genCpl ");
1698     );
1699
1700
1701   /* assign asmOps to operand & result */
1702   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1703   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1704
1705   /* special case if in bit space */
1706   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1707     if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1708       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1709       emitcode ("cpl", "c");
1710       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1711       goto release;
1712     }
1713     tlbl=newiTempLabel(NULL);
1714     emitcode ("cjne", "%s,#0x01,%05d$", 
1715               aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,TRUE), tlbl->key+100);
1716     emitcode ("", "%05d$:", tlbl->key+100);
1717     outBitC (IC_RESULT(ic));
1718     goto release;
1719   }
1720
1721   size = AOP_SIZE (IC_RESULT (ic));
1722   _startLazyDPSEvaluation ();
1723   while (size--)
1724     {
1725       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1726       MOVA (l);
1727       emitcode ("cpl", "a");
1728       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1729     }
1730   _endLazyDPSEvaluation ();
1731
1732
1733 release:
1734   /* release the aops */
1735   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1736   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1737 }
1738
1739 /*-----------------------------------------------------------------*/
1740 /* genUminusFloat - unary minus for floating points                */
1741 /*-----------------------------------------------------------------*/
1742 static void
1743 genUminusFloat (operand * op, operand * result)
1744 {
1745   int size, offset = 0;
1746   char *l;
1747   /* for this we just need to flip the
1748      first it then copy the rest in place */
1749   D (emitcode (";", "genUminusFloat");
1750     );
1751
1752   _startLazyDPSEvaluation ();
1753   size = AOP_SIZE (op) - 1;
1754   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1755   MOVA (l);
1756
1757   emitcode ("cpl", "acc.7");
1758   aopPut (AOP (result), "a", 3);
1759
1760   while (size--)
1761     {
1762       aopPut (AOP (result),
1763               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1764               offset);
1765       offset++;
1766     }
1767   _endLazyDPSEvaluation ();
1768 }
1769
1770 /*-----------------------------------------------------------------*/
1771 /* genUminus - unary minus code generation                         */
1772 /*-----------------------------------------------------------------*/
1773 static void
1774 genUminus (iCode * ic)
1775 {
1776   int offset, size;
1777   sym_link *optype, *rtype;
1778
1779   D (emitcode (";", "genUminus ");
1780     );
1781
1782
1783   /* assign asmops */
1784   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1785   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1786
1787   /* if both in bit space then special
1788      case */
1789   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1790       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1791     {
1792
1793       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1794       emitcode ("cpl", "c");
1795       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1796       goto release;
1797     }
1798
1799   optype = operandType (IC_LEFT (ic));
1800   rtype = operandType (IC_RESULT (ic));
1801
1802   /* if float then do float stuff */
1803   if (IS_FLOAT (optype))
1804     {
1805       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1806       goto release;
1807     }
1808
1809   /* otherwise subtract from zero */
1810   size = AOP_SIZE (IC_LEFT (ic));
1811   offset = 0;
1812   _startLazyDPSEvaluation ();
1813   while (size--)
1814     {
1815       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1816       if (!strcmp (l, "a"))
1817         {
1818           if (offset == 0)
1819             SETC;
1820           emitcode ("cpl", "a");
1821           emitcode ("addc", "a,#0");
1822         }
1823       else
1824         {
1825           if (offset == 0)
1826             CLRC;
1827           emitcode ("clr", "a");
1828           emitcode ("subb", "a,%s", l);
1829         }
1830       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1831     }
1832   _endLazyDPSEvaluation ();
1833
1834   /* if any remaining bytes in the result */
1835   /* we just need to propagate the sign   */
1836   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1837     {
1838       emitcode ("rlc", "a");
1839       emitcode ("subb", "a,acc");
1840       while (size--)
1841         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1842     }
1843
1844 release:
1845   /* release the aops */
1846   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1847   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1848 }
1849
1850 /*-----------------------------------------------------------------*/
1851 /* savermask - saves registers in the mask                         */
1852 /*-----------------------------------------------------------------*/
1853 static void savermask(bitVect *rs_mask)
1854 {
1855     int i;
1856     if (options.useXstack) {
1857         if (bitVectBitValue (rs_mask, R0_IDX))
1858             emitcode ("mov", "b,r0");
1859         emitcode ("mov", "r0,%s", spname);
1860         for (i = 0; i < ds390_nRegs; i++) {
1861             if (bitVectBitValue (rs_mask, i)) {
1862                 if (i == R0_IDX)
1863                     emitcode ("mov", "a,b");
1864                 else
1865                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1866                 emitcode ("movx", "@r0,a");
1867                 emitcode ("inc", "r0");
1868             }
1869         }
1870         emitcode ("mov", "%s,r0", spname);
1871         if (bitVectBitValue (rs_mask, R0_IDX))
1872             emitcode ("mov", "r0,b");
1873     } else {
1874         for (i = 0; i < ds390_nRegs; i++) {
1875             if (bitVectBitValue (rs_mask, i))
1876                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1877         }
1878     }
1879 }
1880
1881 /*-----------------------------------------------------------------*/
1882 /* saveRegisters - will look for a call and save the registers     */
1883 /*-----------------------------------------------------------------*/
1884 static void
1885 saveRegisters (iCode * lic)
1886 {
1887   iCode *ic;
1888   bitVect *rsave;
1889
1890   /* look for call */
1891   for (ic = lic; ic; ic = ic->next)
1892     if (ic->op == CALL || ic->op == PCALL)
1893       break;
1894
1895   if (!ic)
1896     {
1897       fprintf (stderr, "found parameter push with no function call\n");
1898       return;
1899     }
1900
1901   /* if the registers have been saved already then
1902      do nothing */
1903   if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1904
1905   /* special case if DPTR alive across a function call then must save it 
1906      even though callee saves */
1907   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1908       int i =0;
1909       rsave = newBitVect(ic->rMask->size);
1910       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1911           if (bitVectBitValue(ic->rMask,i))
1912               rsave = bitVectSetBit(rsave,i);
1913       }
1914       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1915   } else {
1916     /* safe the registers in use at this time but skip the
1917        ones for the result */
1918     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1919                            ds390_rUmaskForOp (IC_RESULT(ic)));
1920   }
1921   ic->regsSaved = 1;
1922   savermask(rsave);
1923 }
1924
1925 /*-----------------------------------------------------------------*/
1926 /* usavermask - restore registers with mask                        */
1927 /*-----------------------------------------------------------------*/
1928 static void unsavermask(bitVect *rs_mask)
1929 {
1930     int i;
1931     if (options.useXstack) {
1932         emitcode ("mov", "r0,%s", spname);
1933         for (i = ds390_nRegs; i >= 0; i--) {
1934             if (bitVectBitValue (rs_mask, i)) {
1935                 emitcode ("dec", "r0");
1936                 emitcode ("movx", "a,@r0");
1937                 if (i == R0_IDX)
1938                     emitcode ("mov", "b,a");
1939                 else
1940                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1941             }       
1942         }
1943         emitcode ("mov", "%s,r0", spname);
1944         if (bitVectBitValue (rs_mask, R0_IDX))
1945             emitcode ("mov", "r0,b");
1946     } else {
1947         for (i = ds390_nRegs; i >= 0; i--) {
1948             if (bitVectBitValue (rs_mask, i))
1949                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1950         }
1951     }
1952 }
1953
1954 /*-----------------------------------------------------------------*/
1955 /* unsaveRegisters - pop the pushed registers                      */
1956 /*-----------------------------------------------------------------*/
1957 static void
1958 unsaveRegisters (iCode * ic)
1959 {
1960   bitVect *rsave;
1961
1962   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1963       int i =0;
1964       rsave = newBitVect(ic->rMask->size);
1965       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1966           if (bitVectBitValue(ic->rMask,i))
1967               rsave = bitVectSetBit(rsave,i);
1968       }
1969       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1970   } else {
1971     /* restore the registers in use at this time but skip the
1972        ones for the result */
1973     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
1974                            ds390_rUmaskForOp (IC_RESULT(ic)));
1975   }
1976   unsavermask(rsave);
1977 }
1978
1979
1980 /*-----------------------------------------------------------------*/
1981 /* pushSide -                */
1982 /*-----------------------------------------------------------------*/
1983 static void
1984 pushSide (operand * oper, int size)
1985 {
1986   int offset = 0;
1987   _startLazyDPSEvaluation ();
1988   while (size--)
1989     {
1990       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1991       if (AOP_TYPE (oper) != AOP_REG &&
1992           AOP_TYPE (oper) != AOP_DIR &&
1993           strcmp (l, "a"))
1994         {
1995           emitcode ("mov", "a,%s", l);
1996           emitcode ("push", "acc");
1997         }
1998       else
1999         emitcode ("push", "%s", l);
2000     }
2001   _endLazyDPSEvaluation ();
2002 }
2003
2004 /*-----------------------------------------------------------------*/
2005 /* assignResultValue -               */
2006 /*-----------------------------------------------------------------*/
2007 static void
2008 assignResultValue (operand * oper)
2009 {
2010   int offset = 0;
2011   int size = AOP_SIZE (oper);
2012
2013   _startLazyDPSEvaluation ();
2014   while (size--)
2015     {
2016       aopPut (AOP (oper), fReturn[offset], offset);
2017       offset++;
2018     }
2019   _endLazyDPSEvaluation ();
2020 }
2021
2022
2023 /*-----------------------------------------------------------------*/
2024 /* genXpush - pushes onto the external stack                       */
2025 /*-----------------------------------------------------------------*/
2026 static void
2027 genXpush (iCode * ic)
2028 {
2029   asmop *aop = newAsmop (0);
2030   regs *r;
2031   int size, offset = 0;
2032
2033   D (emitcode (";", "genXpush ");
2034     );
2035
2036   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2037   r = getFreePtr (ic, &aop, FALSE);
2038
2039
2040   emitcode ("mov", "%s,_spx", r->name);
2041
2042   size = AOP_SIZE (IC_LEFT (ic));
2043   _startLazyDPSEvaluation ();
2044   while (size--)
2045     {
2046
2047       char *l = aopGet (AOP (IC_LEFT (ic)),
2048                         offset++, FALSE, FALSE, TRUE);
2049       MOVA (l);
2050       emitcode ("movx", "@%s,a", r->name);
2051       emitcode ("inc", "%s", r->name);
2052
2053     }
2054   _endLazyDPSEvaluation ();
2055
2056
2057   emitcode ("mov", "_spx,%s", r->name);
2058
2059   freeAsmop (NULL, aop, ic, TRUE);
2060   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2061 }
2062
2063 /*-----------------------------------------------------------------*/
2064 /* genIpush - genrate code for pushing this gets a little complex  */
2065 /*-----------------------------------------------------------------*/
2066 static void
2067 genIpush (iCode * ic)
2068 {
2069   int size, offset = 0;
2070   char *l;
2071
2072   D (emitcode (";", "genIpush ");
2073     );
2074
2075   /* if this is not a parm push : ie. it is spill push
2076      and spill push is always done on the local stack */
2077   if (!ic->parmPush)
2078     {
2079
2080       /* and the item is spilt then do nothing */
2081       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2082         return;
2083
2084       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2085       size = AOP_SIZE (IC_LEFT (ic));
2086       /* push it on the stack */
2087       _startLazyDPSEvaluation ();
2088       while (size--)
2089         {
2090           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2091           if (*l == '#')
2092             {
2093               MOVA (l);
2094               l = "acc";
2095             }
2096           emitcode ("push", "%s", l);
2097         }
2098       _endLazyDPSEvaluation ();
2099       return;
2100     }
2101
2102   /* this is a paramter push: in this case we call
2103      the routine to find the call and save those
2104      registers that need to be saved */
2105   saveRegisters (ic);
2106
2107   /* if use external stack then call the external
2108      stack pushing routine */
2109   if (options.useXstack)
2110     {
2111       genXpush (ic);
2112       return;
2113     }
2114
2115   /* then do the push */
2116   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2117
2118   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2119   size = AOP_SIZE (IC_LEFT (ic));
2120
2121   _startLazyDPSEvaluation ();
2122   while (size--)
2123     {
2124       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2125       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2126           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2127           strcmp (l, "a"))
2128         {
2129           emitcode ("mov", "a,%s", l);
2130           emitcode ("push", "acc");
2131         }
2132       else
2133         emitcode ("push", "%s", l);
2134     }
2135   _endLazyDPSEvaluation ();
2136
2137   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2138 }
2139
2140 /*-----------------------------------------------------------------*/
2141 /* genIpop - recover the registers: can happen only for spilling   */
2142 /*-----------------------------------------------------------------*/
2143 static void
2144 genIpop (iCode * ic)
2145 {
2146   int size, offset;
2147
2148   D (emitcode (";", "genIpop ");
2149     );
2150
2151
2152   /* if the temp was not pushed then */
2153   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2154     return;
2155
2156   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2157   size = AOP_SIZE (IC_LEFT (ic));
2158   offset = (size - 1);
2159   _startLazyDPSEvaluation ();
2160   while (size--)
2161     {
2162       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2163                                      FALSE, TRUE, TRUE));
2164     }
2165   _endLazyDPSEvaluation ();
2166
2167   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2168 }
2169
2170 /*-----------------------------------------------------------------*/
2171 /* unsaveRBank - restores the resgister bank from stack            */
2172 /*-----------------------------------------------------------------*/
2173 static void
2174 unsaveRBank (int bank, iCode * ic, bool popPsw)
2175 {
2176   int i;
2177   asmop *aop = NULL;
2178   regs *r = NULL;
2179
2180   if (options.useXstack)
2181   {
2182       if (!ic)
2183       {
2184           /* Assume r0 is available for use. */
2185           r = ds390_regWithIdx (R0_IDX);;          
2186       } 
2187       else
2188       {
2189           aop = newAsmop (0);
2190           r = getFreePtr (ic, &aop, FALSE);
2191       }
2192       emitcode ("mov", "%s,_spx", r->name);      
2193   }
2194   
2195   if (popPsw)
2196     {
2197       if (options.useXstack)
2198       {
2199           emitcode ("movx", "a,@%s", r->name);
2200           emitcode ("mov", "psw,a");
2201           emitcode ("dec", "%s", r->name);
2202         }
2203       else
2204       {
2205         emitcode ("pop", "psw");
2206       }
2207     }
2208
2209   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2210     {
2211       if (options.useXstack)
2212         {
2213           emitcode ("movx", "a,@%s", r->name);
2214           emitcode ("mov", "(%s+%d),a",
2215                     regs390[i].base, 8 * bank + regs390[i].offset);
2216           emitcode ("dec", "%s", r->name);
2217
2218         }
2219       else
2220         emitcode ("pop", "(%s+%d)",
2221                   regs390[i].base, 8 * bank + regs390[i].offset);
2222     }
2223
2224   if (options.useXstack)
2225     {
2226       emitcode ("mov", "_spx,%s", r->name);
2227     }
2228     
2229   if (aop)
2230   {
2231       freeAsmop (NULL, aop, ic, TRUE);  
2232   }    
2233 }
2234
2235 /*-----------------------------------------------------------------*/
2236 /* saveRBank - saves an entire register bank on the stack          */
2237 /*-----------------------------------------------------------------*/
2238 static void
2239 saveRBank (int bank, iCode * ic, bool pushPsw)
2240 {
2241   int i;
2242   asmop *aop = NULL;
2243   regs *r = NULL;
2244
2245   if (options.useXstack)
2246     {
2247         if (!ic)
2248         {
2249           /* Assume r0 is available for use. */
2250                   r = ds390_regWithIdx (R0_IDX);;
2251         }
2252         else
2253         {
2254           aop = newAsmop (0);
2255           r = getFreePtr (ic, &aop, FALSE);
2256         }
2257         emitcode ("mov", "%s,_spx", r->name);    
2258     }
2259
2260   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2261     {
2262       if (options.useXstack)
2263         {
2264           emitcode ("inc", "%s", r->name);
2265           emitcode ("mov", "a,(%s+%d)",
2266                     regs390[i].base, 8 * bank + regs390[i].offset);
2267           emitcode ("movx", "@%s,a", r->name);
2268         }
2269       else
2270         emitcode ("push", "(%s+%d)",
2271                   regs390[i].base, 8 * bank + regs390[i].offset);
2272     }
2273
2274   if (pushPsw)
2275     {
2276       if (options.useXstack)
2277         {
2278           emitcode ("mov", "a,psw");
2279           emitcode ("movx", "@%s,a", r->name);
2280           emitcode ("inc", "%s", r->name);
2281           emitcode ("mov", "_spx,%s", r->name);
2282         }
2283       else
2284       {
2285         emitcode ("push", "psw");
2286       }
2287
2288       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2289     }
2290   
2291   if (aop)
2292   {
2293        freeAsmop (NULL, aop, ic, TRUE);
2294   }    
2295     
2296   if (ic)
2297   {  
2298       ic->bankSaved = 1;
2299   }
2300 }
2301
2302 /*-----------------------------------------------------------------*/
2303 /* genCall - generates a call statement                            */
2304 /*-----------------------------------------------------------------*/
2305 static void
2306 genCall (iCode * ic)
2307 {
2308   sym_link *dtype;
2309   bool restoreBank = FALSE;
2310   bool swapBanks = FALSE;
2311
2312   D (emitcode (";", "genCall "););
2313
2314   /* if we are calling a not _naked function that is not using
2315      the same register bank then we need to save the
2316      destination registers on the stack */
2317   dtype = operandType (IC_LEFT (ic));
2318   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2319       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2320       IFFUNC_ISISR (currFunc->type))
2321   {
2322       if (!ic->bankSaved) 
2323       {
2324            /* This is unexpected; the bank should have been saved in
2325             * genFunction.
2326             */
2327            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2328            restoreBank = TRUE;
2329       }
2330       swapBanks = TRUE;
2331   }
2332   
2333     /* if caller saves & we have not saved then */
2334     if (!ic->regsSaved)
2335       saveRegisters (ic);
2336   
2337   /* if send set is not empty the assign */
2338   /* We've saved all the registers we care about;
2339   * therefore, we may clobber any register not used
2340   * in the calling convention (i.e. anything not in
2341   * fReturn.
2342   */
2343   if (_G.sendSet)
2344     {
2345       iCode *sic;
2346
2347       for (sic = setFirstItem (_G.sendSet); sic;
2348            sic = setNextItem (_G.sendSet))
2349         {
2350           int size, offset = 0;
2351
2352           // we know that dpl(hxb) is the result, so
2353           _startLazyDPSEvaluation ();
2354           size=getSize(operandType(IC_LEFT(sic)));
2355           if (size>1) {
2356             aopOp (IC_LEFT (sic), sic, FALSE, 
2357                    (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2358           } else {
2359             aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2360           }
2361           while (size--)
2362             {
2363               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2364                                 FALSE, FALSE, TRUE);
2365               if (strcmp (l, fReturn[offset]))
2366                 {
2367                   emitcode ("mov", "%s,%s",
2368                             fReturn[offset],
2369                             l);
2370                 }
2371               offset++;
2372             }
2373           _endLazyDPSEvaluation ();
2374           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2375         }
2376       _G.sendSet = NULL;
2377     }  
2378     
2379   if (swapBanks)
2380   {
2381         emitcode ("mov", "psw,#!constbyte", 
2382            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2383   }
2384
2385   /* make the call */
2386   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2387                             OP_SYMBOL (IC_LEFT (ic))->rname :
2388                             OP_SYMBOL (IC_LEFT (ic))->name));
2389
2390   if (swapBanks)
2391   {
2392        emitcode ("mov", "psw,#!constbyte", 
2393           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2394   }
2395
2396   /* if we need assign a result value */
2397   if ((IS_ITEMP (IC_RESULT (ic)) &&
2398        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2399         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2400         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2401       IS_TRUE_SYMOP (IC_RESULT (ic)))
2402     {
2403       if (isOperandInFarSpace (IC_RESULT (ic))
2404           && getSize (operandType (IC_RESULT (ic))) <= 2)
2405         {
2406           int size = getSize (operandType (IC_RESULT (ic)));
2407
2408           /* Special case for 1 or 2 byte return in far space. */
2409           MOVA (fReturn[0]);
2410           if (size > 1)
2411             {
2412               emitcode ("mov", "b,%s", fReturn[1]);
2413             }
2414
2415           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2416           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2417
2418           if (size > 1)
2419             {
2420               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2421             }
2422           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2423         }
2424       else
2425         {
2426           _G.accInUse++;
2427           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2428           _G.accInUse--;
2429
2430           assignResultValue (IC_RESULT (ic));
2431
2432           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2433         }
2434     }
2435
2436   /* adjust the stack for parameters if
2437      required */
2438   if (ic->parmBytes) {
2439       int i;
2440       if (options.stack10bit) {
2441           if (ic->parmBytes <= 4) {
2442               emitcode(";","stack adjustment for parms");
2443               for (i=0; i < ic->parmBytes ; i++) {
2444                   emitcode("pop","acc");
2445               }
2446           } else {
2447               emitcode ("clr","c");
2448               emitcode ("mov","a,sp");
2449               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2450               emitcode ("mov","sp,a");
2451               emitcode ("mov","a,esp");
2452               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2453               emitcode ("mov","esp,a");   
2454           }
2455       } else {
2456           if (ic->parmBytes > 3) {
2457               emitcode ("mov", "a,%s", spname);
2458               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2459               emitcode ("mov", "%s,a", spname);
2460           } else
2461               for (i = 0; i < ic->parmBytes; i++)
2462                   emitcode ("dec", "%s", spname);
2463       }
2464   }
2465
2466   /* if we hade saved some registers then unsave them */
2467   if (ic->regsSaved)
2468     unsaveRegisters (ic);
2469
2470   /* if register bank was saved then pop them */
2471   if (restoreBank)
2472     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2473 }
2474
2475 /*-----------------------------------------------------------------*/
2476 /* genPcall - generates a call by pointer statement                */
2477 /*-----------------------------------------------------------------*/
2478 static void
2479 genPcall (iCode * ic)
2480 {
2481   sym_link *dtype;
2482   symbol *rlbl = newiTempLabel (NULL);
2483   bool restoreBank=FALSE;
2484
2485   D (emitcode (";", "genPcall ");
2486     );
2487
2488
2489   /* if caller saves & we have not saved then */
2490   if (!ic->regsSaved)
2491     saveRegisters (ic);
2492
2493   /* if we are calling a function that is not using
2494      the same register bank then we need to save the
2495      destination registers on the stack */
2496   dtype = operandType (IC_LEFT (ic));
2497   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2498       IFFUNC_ISISR (currFunc->type) &&
2499       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2500     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2501     restoreBank=TRUE;
2502   }
2503
2504   /* push the return address on to the stack */
2505   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2506   emitcode ("push", "acc");
2507   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2508   emitcode ("push", "acc");
2509
2510   if (options.model == MODEL_FLAT24)
2511     {
2512       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2513       emitcode ("push", "acc");
2514     }
2515
2516   /* now push the calling address */
2517   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2518
2519   pushSide (IC_LEFT (ic), FPTRSIZE);
2520
2521   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2522
2523   /* if send set is not empty the assign */
2524   if (_G.sendSet)
2525     {
2526       iCode *sic;
2527
2528       for (sic = setFirstItem (_G.sendSet); sic;
2529            sic = setNextItem (_G.sendSet))
2530         {
2531           int size, offset = 0;
2532
2533           // we know that dpl(hxb) is the result, so
2534           _startLazyDPSEvaluation ();
2535           size=getSize(operandType(IC_LEFT(sic)));
2536           if (size>1) {
2537             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2538           } else {
2539             aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2540           }
2541           while (size--)
2542             {
2543               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2544                                 FALSE, FALSE, TRUE);
2545               if (strcmp (l, fReturn[offset]))
2546                 {
2547                   emitcode ("mov", "%s,%s",
2548                             fReturn[offset],
2549                             l);
2550                 }
2551               offset++;
2552             }
2553           _endLazyDPSEvaluation ();
2554           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2555         }
2556       _G.sendSet = NULL;
2557     }
2558
2559   emitcode ("ret", "");
2560   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2561
2562
2563   /* if we need assign a result value */
2564   if ((IS_ITEMP (IC_RESULT (ic)) &&
2565        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2566         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2567       IS_TRUE_SYMOP (IC_RESULT (ic)))
2568     {
2569
2570       _G.accInUse++;
2571       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2572       _G.accInUse--;
2573
2574       assignResultValue (IC_RESULT (ic));
2575
2576       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2577     }
2578
2579   /* adjust the stack for parameters if
2580      required */
2581   if (ic->parmBytes)
2582     {
2583       int i;
2584       if (ic->parmBytes > 3)
2585         {
2586           emitcode ("mov", "a,%s", spname);
2587           emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2588           emitcode ("mov", "%s,a", spname);
2589         }
2590       else
2591         for (i = 0; i < ic->parmBytes; i++)
2592           emitcode ("dec", "%s", spname);
2593
2594     }
2595
2596   /* if register bank was saved then unsave them */
2597   if (restoreBank)
2598     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2599   
2600   /* if we hade saved some registers then
2601      unsave them */
2602   if (ic->regsSaved)
2603     unsaveRegisters (ic);
2604
2605 }
2606
2607 /*-----------------------------------------------------------------*/
2608 /* resultRemat - result  is rematerializable                       */
2609 /*-----------------------------------------------------------------*/
2610 static int
2611 resultRemat (iCode * ic)
2612 {
2613   if (SKIP_IC (ic) || ic->op == IFX)
2614     return 0;
2615
2616   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2617     {
2618       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2619       if (sym->remat && !POINTER_SET (ic))
2620         return 1;
2621     }
2622
2623   return 0;
2624 }
2625
2626 #if defined(__BORLANDC__) || defined(_MSC_VER)
2627 #define STRCASECMP stricmp
2628 #else
2629 #define STRCASECMP strcasecmp
2630 #endif
2631
2632 /*-----------------------------------------------------------------*/
2633 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2634 /*-----------------------------------------------------------------*/
2635 static bool
2636 inExcludeList (char *s)
2637 {
2638   int i = 0;
2639
2640   if (options.excludeRegs[i] &&
2641       STRCASECMP (options.excludeRegs[i], "none") == 0)
2642     return FALSE;
2643
2644   for (i = 0; options.excludeRegs[i]; i++)
2645     {
2646       if (options.excludeRegs[i] &&
2647           STRCASECMP (s, options.excludeRegs[i]) == 0)
2648         return TRUE;
2649     }
2650   return FALSE;
2651 }
2652
2653 /*-----------------------------------------------------------------*/
2654 /* genFunction - generated code for function entry                 */
2655 /*-----------------------------------------------------------------*/
2656 static void
2657 genFunction (iCode * ic)
2658 {
2659   symbol *sym;
2660   sym_link *ftype;
2661   bool   switchedPSW = FALSE;
2662
2663   D (emitcode (";", "genFunction "););
2664
2665   _G.nRegsSaved = 0;
2666   /* create the function header */
2667   emitcode (";", "-----------------------------------------");
2668   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2669   emitcode (";", "-----------------------------------------");
2670
2671   emitcode ("", "%s:", sym->rname);
2672   ftype = operandType (IC_LEFT (ic));
2673
2674   if (IFFUNC_ISNAKED(ftype))
2675   {
2676       emitcode(";", "naked function: no prologue.");
2677       return;
2678   }
2679   
2680   if (options.stack_probe) 
2681       emitcode ("lcall","__stack_probe");
2682   /* if critical function then turn interrupts off */
2683   if (IFFUNC_ISCRITICAL (ftype))
2684     emitcode ("clr", "ea");
2685
2686   /* here we need to generate the equates for the
2687      register bank if required */
2688   if (FUNC_REGBANK (ftype) != rbank)
2689     {
2690       int i;
2691
2692       rbank = FUNC_REGBANK (ftype);
2693       for (i = 0; i < ds390_nRegs; i++)
2694         {
2695           if (regs390[i].print) {
2696               if (strcmp (regs390[i].base, "0") == 0)
2697                   emitcode ("", "%s !equ !constbyte",
2698                             regs390[i].dname,
2699                             8 * rbank + regs390[i].offset);
2700               else
2701                   emitcode ("", "%s !equ %s + !constbyte",
2702                             regs390[i].dname,
2703                             regs390[i].base,
2704                             8 * rbank + regs390[i].offset);
2705           }
2706         }
2707     }
2708
2709   /* if this is an interrupt service routine then
2710      save acc, b, dpl, dph  */
2711   if (IFFUNC_ISISR (sym->type))
2712     {
2713
2714       if (!inExcludeList ("acc"))
2715         emitcode ("push", "acc");
2716       if (!inExcludeList ("b"))
2717         emitcode ("push", "b");
2718       if (!inExcludeList ("dpl"))
2719         emitcode ("push", "dpl");
2720       if (!inExcludeList ("dph"))
2721         emitcode ("push", "dph");
2722       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2723         {
2724           emitcode ("push", "dpx");
2725           /* Make sure we're using standard DPTR */
2726           emitcode ("push", "dps");
2727           emitcode ("mov", "dps,#0");
2728           if (options.stack10bit)
2729             {
2730               /* This ISR could conceivably use DPTR2. Better save it. */
2731               emitcode ("push", "dpl1");
2732               emitcode ("push", "dph1");
2733               emitcode ("push", "dpx1");
2734               emitcode ("push",  DP2_RESULT_REG);
2735             }
2736         }
2737       /* if this isr has no bank i.e. is going to
2738          run with bank 0 , then we need to save more
2739          registers :-) */
2740       if (!FUNC_REGBANK (sym->type))
2741         {
2742
2743           /* if this function does not call any other
2744              function then we can be economical and
2745              save only those registers that are used */
2746           if (!IFFUNC_HASFCALL(sym->type))
2747             {
2748               int i;
2749
2750               /* if any registers used */
2751               if (sym->regsUsed)
2752                 {
2753                   /* save the registers used */
2754                   for (i = 0; i < sym->regsUsed->size; i++)
2755                     {
2756                       if (bitVectBitValue (sym->regsUsed, i) ||
2757                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2758                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2759                     }
2760                 }
2761
2762             }
2763           else
2764             {
2765               /* this function has  a function call cannot
2766                  determines register usage so we will have to push the
2767                  entire bank */
2768               saveRBank (0, ic, FALSE);
2769             }
2770         }
2771         else
2772         {
2773             /* This ISR uses a non-zero bank.
2774              *
2775              * We assume that the bank is available for our
2776              * exclusive use.
2777              *
2778              * However, if this ISR calls a function which uses some
2779              * other bank, we must save that bank entirely.
2780              */
2781             unsigned long banksToSave = 0;
2782             
2783             if (IFFUNC_HASFCALL(sym->type))
2784             {
2785
2786 #define MAX_REGISTER_BANKS 4
2787
2788                 iCode *i;
2789                 int ix;
2790
2791                 for (i = ic; i; i = i->next)
2792                 {
2793                     if (i->op == ENDFUNCTION)
2794                     {
2795                         /* we got to the end OK. */
2796                         break;
2797                     }
2798                     
2799                     if (i->op == CALL)
2800                     {
2801                         sym_link *dtype;
2802                         
2803                         dtype = operandType (IC_LEFT(i));
2804                         if (dtype 
2805                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2806                         {
2807                              /* Mark this bank for saving. */
2808                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2809                              {
2810                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2811                              }
2812                              else
2813                              {
2814                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2815                              }
2816                              
2817                              /* And note that we don't need to do it in 
2818                               * genCall.
2819                               */
2820                              i->bankSaved = 1;
2821                         }
2822                     }
2823                     if (i->op == PCALL)
2824                     {
2825                         /* This is a mess; we have no idea what
2826                          * register bank the called function might
2827                          * use.
2828                          *
2829                          * The only thing I can think of to do is
2830                          * throw a warning and hope.
2831                          */
2832                         werror(W_FUNCPTR_IN_USING_ISR);   
2833                     }
2834                 }
2835
2836                 if (banksToSave && options.useXstack)
2837                 {
2838                     /* Since we aren't passing it an ic, 
2839                      * saveRBank will assume r0 is available to abuse.
2840                      *
2841                      * So switch to our (trashable) bank now, so
2842                      * the caller's R0 isn't trashed.
2843                      */
2844                     emitcode ("push", "psw");
2845                     emitcode ("mov", "psw,#!constbyte", 
2846                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2847                     switchedPSW = TRUE;
2848                 }
2849                 
2850                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2851                 {
2852                      if (banksToSave & (1 << ix))
2853                      {
2854                          saveRBank(ix, NULL, FALSE);
2855                      }
2856                 }
2857             }
2858             // jwk: this needs a closer look
2859             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2860         }
2861     }
2862   else
2863     {
2864       /* if callee-save to be used for this function
2865          then save the registers being used in this function */
2866       if (IFFUNC_CALLEESAVES(sym->type))
2867         {
2868           int i;
2869
2870           /* if any registers used */
2871           if (sym->regsUsed)
2872             {
2873               /* save the registers used */
2874               for (i = 0; i < sym->regsUsed->size; i++)
2875                 {
2876                   if (bitVectBitValue (sym->regsUsed, i) ||
2877                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2878                     {
2879                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2880                       _G.nRegsSaved++;
2881                     }
2882                 }
2883             }
2884         }
2885     }
2886
2887   /* set the register bank to the desired value */
2888   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2889    && !switchedPSW)
2890     {
2891       emitcode ("push", "psw");
2892       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2893     }
2894
2895   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2896        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2897       if (options.stack10bit) {
2898           emitcode ("push","_bpx");
2899           emitcode ("push","_bpx+1");
2900           emitcode ("mov","_bpx,%s",spname);
2901           emitcode ("mov","_bpx+1,esp");
2902           emitcode ("anl","_bpx+1,#3");
2903       } else {
2904           if (options.useXstack) {
2905               emitcode ("mov", "r0,%s", spname);
2906               emitcode ("mov", "a,_bp");
2907               emitcode ("movx", "@r0,a");
2908               emitcode ("inc", "%s", spname);
2909           } else {
2910               /* set up the stack */
2911               emitcode ("push", "_bp"); /* save the callers stack  */
2912           }
2913           emitcode ("mov", "_bp,%s", spname);
2914       }
2915   }
2916
2917   /* adjust the stack for the function */
2918   if (sym->stack) {
2919       int i = sym->stack;
2920       if (options.stack10bit) {
2921           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2922           assert (sym->recvSize <= 4);
2923           emitcode ("mov","a,sp");
2924           emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
2925           emitcode ("mov","sp,a");
2926           emitcode ("mov","a,esp");
2927           emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
2928           emitcode ("mov","esp,a");
2929       } else {
2930           if (i > 256)
2931               werror (W_STACK_OVERFLOW, sym->name);
2932           
2933           if (i > 3 && sym->recvSize < 4) {
2934               
2935               emitcode ("mov", "a,sp");
2936               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
2937               emitcode ("mov", "sp,a");
2938               
2939           } else
2940               while (i--)
2941                   emitcode ("inc", "sp");
2942       }
2943   }
2944
2945   if (sym->xstack)
2946     {
2947
2948       emitcode ("mov", "a,_spx");
2949       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
2950       emitcode ("mov", "_spx,a");
2951     }
2952
2953 }
2954
2955 /*-----------------------------------------------------------------*/
2956 /* genEndFunction - generates epilogue for functions               */
2957 /*-----------------------------------------------------------------*/
2958 static void
2959 genEndFunction (iCode * ic)
2960 {
2961   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2962
2963   D (emitcode (";", "genEndFunction "););
2964
2965   if (IFFUNC_ISNAKED(sym->type))
2966   {
2967       emitcode(";", "naked function: no epilogue.");
2968       return;
2969   }
2970
2971   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2972        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2973
2974       if (options.stack10bit) {
2975           emitcode ("mov", "sp,_bpx", spname);
2976           emitcode ("mov", "esp,_bpx+1", spname);
2977       } else {
2978           emitcode ("mov", "%s,_bp", spname);
2979       }
2980   }
2981
2982   /* if use external stack but some variables were
2983      added to the local stack then decrement the
2984      local stack */
2985   if (options.useXstack && sym->stack) {
2986       emitcode ("mov", "a,sp");
2987       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
2988       emitcode ("mov", "sp,a");
2989   }
2990
2991
2992   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2993        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2994
2995       if (options.useXstack) {
2996           emitcode ("mov", "r0,%s", spname);
2997           emitcode ("movx", "a,@r0");
2998           emitcode ("mov", "_bp,a");
2999           emitcode ("dec", "%s", spname);
3000       } else {
3001           if (options.stack10bit) {
3002               emitcode ("pop", "_bpx+1");
3003               emitcode ("pop", "_bpx");
3004           } else {
3005               emitcode ("pop", "_bp");
3006           }
3007       }
3008   }
3009
3010   /* restore the register bank  */
3011   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3012   {
3013     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3014      || !options.useXstack)
3015     {
3016         /* Special case of ISR using non-zero bank with useXstack
3017          * is handled below.
3018          */
3019         emitcode ("pop", "psw");
3020     }
3021   }
3022
3023   if (IFFUNC_ISISR (sym->type))
3024     {
3025
3026       /* now we need to restore the registers */
3027       /* if this isr has no bank i.e. is going to
3028          run with bank 0 , then we need to save more
3029          registers :-) */
3030       if (!FUNC_REGBANK (sym->type))
3031         {
3032           /* if this function does not call any other
3033              function then we can be economical and
3034              save only those registers that are used */
3035           if (!IFFUNC_HASFCALL(sym->type))
3036             {
3037               int i;
3038
3039               /* if any registers used */
3040               if (sym->regsUsed)
3041                 {
3042                   /* save the registers used */
3043                   for (i = sym->regsUsed->size; i >= 0; i--)
3044                     {
3045                       if (bitVectBitValue (sym->regsUsed, i) ||
3046                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3047                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3048                     }
3049                 }
3050
3051             }
3052           else
3053             {
3054               /* this function has  a function call cannot
3055                  determines register usage so we will have to pop the
3056                  entire bank */
3057               unsaveRBank (0, ic, FALSE);
3058             }
3059         }
3060         else
3061         {
3062             /* This ISR uses a non-zero bank.
3063              *
3064              * Restore any register banks saved by genFunction
3065              * in reverse order.
3066              */
3067           // jwk: this needs a closer look
3068             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3069             int ix;
3070           
3071             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3072             {
3073                 if (savedBanks & (1 << ix))
3074                 {
3075                     unsaveRBank(ix, NULL, FALSE);
3076                 }
3077             }
3078             
3079             if (options.useXstack)
3080             {
3081                 /* Restore bank AFTER calling unsaveRBank,
3082                  * since it can trash r0.
3083                  */
3084                 emitcode ("pop", "psw");
3085             }
3086         }
3087
3088       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3089         {
3090           if (options.stack10bit)
3091             {
3092               emitcode ("pop", DP2_RESULT_REG);
3093               emitcode ("pop", "dpx1");
3094               emitcode ("pop", "dph1");
3095               emitcode ("pop", "dpl1");
3096             }
3097           emitcode ("pop", "dps");
3098           emitcode ("pop", "dpx");
3099         }
3100       if (!inExcludeList ("dph"))
3101         emitcode ("pop", "dph");
3102       if (!inExcludeList ("dpl"))
3103         emitcode ("pop", "dpl");
3104       if (!inExcludeList ("b"))
3105         emitcode ("pop", "b");
3106       if (!inExcludeList ("acc"))
3107         emitcode ("pop", "acc");
3108
3109       if (IFFUNC_ISCRITICAL (sym->type))
3110         emitcode ("setb", "ea");
3111
3112       /* if debug then send end of function */
3113       if (options.debug && currFunc) {
3114           _G.debugLine = 1;
3115           emitcode ("", "C$%s$%d$%d$%d ==.",
3116                     FileBaseName (ic->filename), currFunc->lastLine,
3117                     ic->level, ic->block);
3118           if (IS_STATIC (currFunc->etype))
3119             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3120           else
3121             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3122           _G.debugLine = 0;
3123         }
3124
3125       emitcode ("reti", "");
3126     }
3127   else
3128     {
3129       if (IFFUNC_ISCRITICAL (sym->type))
3130         emitcode ("setb", "ea");
3131
3132       if (IFFUNC_CALLEESAVES(sym->type))
3133         {
3134           int i;
3135
3136           /* if any registers used */
3137           if (sym->regsUsed)
3138             {
3139               /* save the registers used */
3140               for (i = sym->regsUsed->size; i >= 0; i--)
3141                 {
3142                   if (bitVectBitValue (sym->regsUsed, i) ||
3143                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3144                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3145                 }
3146             }
3147
3148         }
3149
3150       /* if debug then send end of function */
3151       if (options.debug && currFunc)
3152         {
3153           _G.debugLine = 1;
3154           emitcode ("", "C$%s$%d$%d$%d ==.",
3155                     FileBaseName (ic->filename), currFunc->lastLine,
3156                     ic->level, ic->block);
3157           if (IS_STATIC (currFunc->etype))
3158             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3159           else
3160             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3161           _G.debugLine = 0;
3162         }
3163
3164       emitcode ("ret", "");
3165     }
3166
3167 }
3168
3169 /*-----------------------------------------------------------------*/
3170 /* genJavaNativeRet - generate code for return JavaNative          */
3171 /*-----------------------------------------------------------------*/
3172 static void genJavaNativeRet(iCode *ic)
3173 {
3174     int i, size;
3175
3176     aopOp (IC_LEFT (ic), ic, FALSE, 
3177            (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3178     size = AOP_SIZE (IC_LEFT (ic));
3179
3180     assert (size <= 4);
3181
3182     /* it is assigned to GPR0-R3 then push them */
3183     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3184         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3185         for (i = 0 ; i < size ; i++ ) {
3186             emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));     
3187         }
3188         for (i = (size-1) ; i >= 0 ; i--) {
3189             emitcode ("pop","a%s",javaRet[i]);
3190         }
3191     } else {
3192         for (i = 0 ; i < size ; i++) 
3193             emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3194     }
3195     for (i = size ; i < 4 ; i++ )
3196             emitcode ("mov","%s,#0",javaRet[i]);
3197     return;
3198 }
3199
3200 /*-----------------------------------------------------------------*/
3201 /* genRet - generate code for return statement                     */
3202 /*-----------------------------------------------------------------*/
3203 static void
3204 genRet (iCode * ic)
3205 {
3206   int size, offset = 0, pushed = 0;
3207
3208   D (emitcode (";", "genRet ");
3209     );
3210
3211   /* if we have no return value then
3212      just generate the "ret" */
3213   if (!IC_LEFT (ic))
3214     goto jumpret;
3215
3216   /* if this is a JavaNative function then return 
3217      value in different register */
3218   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3219       genJavaNativeRet(ic);
3220       goto jumpret;
3221   }
3222   /* we have something to return then
3223      move the return value into place */
3224   aopOp (IC_LEFT (ic), ic, FALSE, 
3225          (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3226   size = AOP_SIZE (IC_LEFT (ic));
3227
3228   _startLazyDPSEvaluation ();
3229   while (size--)
3230     {
3231       char *l;
3232       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3233         {
3234           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3235                       FALSE, TRUE, FALSE);
3236           emitcode ("push", "%s", l);
3237           pushed++;
3238         }
3239       else
3240         {
3241           /* Since A is the last element of fReturn,
3242            * is is OK to clobber it in the aopGet.
3243            */
3244           l = aopGet (AOP (IC_LEFT (ic)), offset,
3245                       FALSE, FALSE, TRUE);
3246           if (strcmp (fReturn[offset], l))
3247             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3248         }
3249     }
3250   _endLazyDPSEvaluation ();
3251
3252   if (pushed)
3253     {
3254       while (pushed)
3255         {
3256           pushed--;
3257           if (strcmp (fReturn[pushed], "a"))
3258             emitcode ("pop", fReturn[pushed]);
3259           else
3260             emitcode ("pop", "acc");
3261         }
3262     }
3263   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3264
3265 jumpret:
3266   /* generate a jump to the return label
3267      if the next is not the return statement */
3268   if (!(ic->next && ic->next->op == LABEL &&
3269         IC_LABEL (ic->next) == returnLabel))
3270
3271     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3272
3273 }
3274
3275 /*-----------------------------------------------------------------*/
3276 /* genLabel - generates a label                                    */
3277 /*-----------------------------------------------------------------*/
3278 static void
3279 genLabel (iCode * ic)
3280 {
3281   /* special case never generate */
3282   if (IC_LABEL (ic) == entryLabel)
3283     return;
3284
3285   D (emitcode (";", "genLabel ");
3286     );
3287
3288   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3289 }
3290
3291 /*-----------------------------------------------------------------*/
3292 /* genGoto - generates a ljmp                                      */
3293 /*-----------------------------------------------------------------*/
3294 static void
3295 genGoto (iCode * ic)
3296 {
3297   D (emitcode (";", "genGoto ");
3298     );
3299   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3300 }
3301
3302 /*-----------------------------------------------------------------*/
3303 /* findLabelBackwards: walks back through the iCode chain looking  */
3304 /* for the given label. Returns number of iCode instructions     */
3305 /* between that label and given ic.          */
3306 /* Returns zero if label not found.          */
3307 /*-----------------------------------------------------------------*/
3308 static int
3309 findLabelBackwards (iCode * ic, int key)
3310 {
3311   int count = 0;
3312
3313   while (ic->prev)
3314     {
3315       ic = ic->prev;
3316       count++;
3317
3318       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3319         {
3320           /* printf("findLabelBackwards = %d\n", count); */
3321           return count;
3322         }
3323     }
3324
3325   return 0;
3326 }
3327
3328 /*-----------------------------------------------------------------*/
3329 /* genPlusIncr :- does addition with increment if possible         */
3330 /*-----------------------------------------------------------------*/
3331 static bool
3332 genPlusIncr (iCode * ic)
3333 {
3334   unsigned int icount;
3335   unsigned int size = getDataSize (IC_RESULT (ic));
3336
3337   /* will try to generate an increment */
3338   /* if the right side is not a literal
3339      we cannot */
3340   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3341     return FALSE;
3342
3343   /* if the literal value of the right hand side
3344      is greater than 4 then it is not worth it */
3345   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3346     return FALSE;
3347
3348   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3349       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3350       while (icount--) {
3351           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3352       }
3353       return TRUE;
3354   }
3355   /* if increment 16 bits in register */
3356   if (
3357        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3358        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3359        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3360        (size > 1) &&
3361        (icount == 1))
3362     {
3363       symbol *tlbl;
3364       int emitTlbl;
3365       int labelRange;
3366
3367       /* If the next instruction is a goto and the goto target
3368        * is <= 5 instructions previous to this, we can generate
3369        * jumps straight to that target.
3370        */
3371       if (ic->next && ic->next->op == GOTO
3372           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3373           && labelRange <= 5)
3374         {
3375           emitcode (";", "tail increment optimized (range %d)", labelRange);
3376           tlbl = IC_LABEL (ic->next);
3377           emitTlbl = 0;
3378         }
3379       else
3380         {
3381           tlbl = newiTempLabel (NULL);
3382           emitTlbl = 1;
3383         }
3384       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3385       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3386           IS_AOP_PREG (IC_RESULT (ic)))
3387         emitcode ("cjne", "%s,#0,!tlabel"
3388                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3389                   ,tlbl->key + 100);
3390       else
3391         {
3392           emitcode ("clr", "a");
3393           emitcode ("cjne", "a,%s,!tlabel"
3394                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3395                     ,tlbl->key + 100);
3396         }
3397
3398       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3399       if (size > 2)
3400         {
3401           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3402               IS_AOP_PREG (IC_RESULT (ic)))
3403             emitcode ("cjne", "%s,#0,!tlabel"
3404                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3405                       ,tlbl->key + 100);
3406           else
3407             emitcode ("cjne", "a,%s,!tlabel"
3408                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3409                       ,tlbl->key + 100);
3410
3411           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3412         }
3413       if (size > 3)
3414         {
3415           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3416               IS_AOP_PREG (IC_RESULT (ic)))
3417             emitcode ("cjne", "%s,#0,!tlabel"
3418                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3419                       ,tlbl->key + 100);
3420           else
3421             {
3422               emitcode ("cjne", "a,%s,!tlabel"
3423                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3424                         ,tlbl->key + 100);
3425             }
3426           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3427         }
3428
3429       if (emitTlbl)
3430         {
3431           emitcode ("", "!tlabeldef", tlbl->key + 100);
3432         }
3433       return TRUE;
3434     }
3435
3436   /* if the sizes are greater than 1 then we cannot */
3437   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3438       AOP_SIZE (IC_LEFT (ic)) > 1)
3439     return FALSE;
3440
3441   /* we can if the aops of the left & result match or
3442      if they are in registers and the registers are the
3443      same */
3444   if (
3445        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3446        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3447        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3448     {
3449
3450       if (icount > 3)
3451         {
3452           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3453           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3454           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3455         }
3456       else
3457         {
3458
3459           _startLazyDPSEvaluation ();
3460           while (icount--)
3461             {
3462               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3463             }
3464           _endLazyDPSEvaluation ();
3465         }
3466
3467       return TRUE;
3468     }
3469
3470   return FALSE;
3471 }
3472
3473 /*-----------------------------------------------------------------*/
3474 /* outBitAcc - output a bit in acc                                 */
3475 /*-----------------------------------------------------------------*/
3476 static void
3477 outBitAcc (operand * result)
3478 {
3479   symbol *tlbl = newiTempLabel (NULL);
3480   /* if the result is a bit */
3481   if (AOP_TYPE (result) == AOP_CRY)
3482     {
3483       aopPut (AOP (result), "a", 0);
3484     }
3485   else
3486     {
3487       emitcode ("jz", "!tlabel", tlbl->key + 100);
3488       emitcode ("mov", "a,%s", one);
3489       emitcode ("", "!tlabeldef", tlbl->key + 100);
3490       outAcc (result);
3491     }
3492 }
3493
3494 /*-----------------------------------------------------------------*/
3495 /* genPlusBits - generates code for addition of two bits           */
3496 /*-----------------------------------------------------------------*/
3497 static void
3498 genPlusBits (iCode * ic)
3499 {
3500   D (emitcode (";", "genPlusBits ");
3501     );
3502   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3503     {
3504       symbol *lbl = newiTempLabel (NULL);
3505       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3506       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3507       emitcode ("cpl", "c");
3508       emitcode ("", "!tlabeldef", (lbl->key + 100));
3509       outBitC (IC_RESULT (ic));
3510     }
3511   else
3512     {
3513       emitcode ("clr", "a");
3514       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3515       emitcode ("rlc", "a");
3516       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3517       emitcode ("addc", "a,#0");
3518       outAcc (IC_RESULT (ic));
3519     }
3520 }
3521
3522 static void
3523 adjustArithmeticResult (iCode * ic)
3524 {
3525   if (opIsGptr (IC_RESULT (ic)) &&
3526       opIsGptr (IC_LEFT (ic)) &&
3527       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3528     {
3529       aopPut (AOP (IC_RESULT (ic)),
3530               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3531               GPTRSIZE - 1);
3532     }
3533
3534   if (opIsGptr (IC_RESULT (ic)) &&
3535       opIsGptr (IC_RIGHT (ic)) &&
3536       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3537     {
3538       aopPut (AOP (IC_RESULT (ic)),
3539             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3540               GPTRSIZE - 1);
3541     }
3542
3543   if (opIsGptr (IC_RESULT (ic)) &&
3544       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3545       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3546       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3547       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3548     {
3549       char buffer[5];
3550       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3551       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3552     }
3553 }
3554
3555 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3556       // Please don't bring it back without a really good reason.
3557 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3558 // (because all three operands are in far space).
3559 #define AOP_OP_3(ic) \
3560     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3561     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3562     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3563               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3564     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3565         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3566     { \
3567         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3568         fprintf(stderr,                                  \
3569                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3570     }
3571 #endif
3572
3573 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3574 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3575 // will be set TRUE. The caller must then handle the case specially, noting
3576 // that the IC_RESULT operand is not aopOp'd.
3577 #define AOP_OP_3_NOFATAL(ic, rc) \
3578     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3579     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3580                                   ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3581     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3582         (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3583     { \
3584        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3585        rc = TRUE; \
3586     }  \
3587     else \
3588     { \
3589        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3590                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3591        rc = FALSE; \
3592        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3593            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3594        { \
3595             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3596             fprintf(stderr,                                  \
3597                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3598        } \
3599     }
3600
3601 // aopOp the left & right operands of an ic.
3602 #define AOP_OP_2(ic) \
3603     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3604     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3605
3606 // convienience macro.
3607 #define AOP_SET_LOCALS(ic) \
3608     left = IC_LEFT(ic); \
3609     right = IC_RIGHT(ic); \
3610     result = IC_RESULT(ic);
3611
3612
3613 // Given an integer value of pushedSize bytes on the stack,
3614 // adjust it to be resultSize bytes, either by discarding
3615 // the most significant bytes or by zero-padding.
3616 //
3617 // On exit from this macro, pushedSize will have been adjusted to
3618 // equal resultSize, and ACC may be trashed.
3619 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3620       /* If the pushed data is bigger than the result,          \
3621        * simply discard unused bytes. Icky, but works.          \
3622        */                                                       \
3623       while (pushedSize > resultSize)                           \
3624       {                                                         \
3625           D (emitcode (";", "discarding unused result byte."););\
3626           emitcode ("pop", "acc");                              \
3627           pushedSize--;                                         \
3628       }                                                         \
3629       if (pushedSize < resultSize)                              \
3630       {                                                         \
3631           emitcode ("clr", "a");                                \
3632           /* Conversly, we haven't pushed enough here.          \
3633            * just zero-pad, and all is well.                    \
3634            */                                                   \
3635           while (pushedSize < resultSize)                       \
3636           {                                                     \
3637               emitcode("push", "acc");                          \
3638               pushedSize++;                                     \
3639           }                                                     \
3640       }                                                         \
3641       assert(pushedSize == resultSize);
3642
3643 /*-----------------------------------------------------------------*/
3644 /* genPlus - generates code for addition                           */
3645 /*-----------------------------------------------------------------*/
3646 static void
3647 genPlus (iCode * ic)
3648 {
3649   int size, offset = 0;
3650   bool pushResult = FALSE;
3651   int rSize;
3652
3653   D (emitcode (";", "genPlus "););
3654
3655   /* special cases :- */
3656   if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3657       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3658       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3659       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3660       if (size <= 9) {
3661           while (size--) emitcode ("inc","dptr");
3662       } else {
3663           emitcode ("mov","a,dpl");
3664           emitcode ("add","a,#!constbyte",size & 0xff);
3665           emitcode ("mov","dpl,a");
3666           emitcode ("mov","a,dph");
3667           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3668           emitcode ("mov","dph,a");
3669           emitcode ("mov","a,dpx");
3670           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3671           emitcode ("mov","dpx,a");
3672       }
3673       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3674       return ;
3675   }
3676   if ( IS_SYMOP(IC_LEFT(ic)) && 
3677        OP_SYMBOL(IC_LEFT(ic))->remat &&
3678        isOperandInFarSpace(IC_RIGHT(ic))) {
3679       operand *op = IC_RIGHT(ic);
3680       IC_RIGHT(ic) = IC_LEFT(ic);
3681       IC_LEFT(ic) = op;
3682   }
3683                 
3684   AOP_OP_3_NOFATAL (ic, pushResult);
3685   if (pushResult)
3686     {
3687       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3688     }
3689
3690   if (!pushResult)
3691     {
3692       /* if literal, literal on the right or
3693          if left requires ACC or right is already
3694          in ACC */
3695       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3696        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3697           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3698         {
3699           operand *t = IC_RIGHT (ic);
3700           IC_RIGHT (ic) = IC_LEFT (ic);
3701           IC_LEFT (ic) = t;
3702           emitcode (";", "Swapped plus args.");
3703         }
3704
3705       /* if both left & right are in bit
3706          space */
3707       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3708           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3709         {
3710           genPlusBits (ic);
3711           goto release;
3712         }
3713
3714       /* if left in bit space & right literal */
3715       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3716           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3717         {
3718           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3719           /* if result in bit space */
3720           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3721             {
3722               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3723                 emitcode ("cpl", "c");
3724               outBitC (IC_RESULT (ic));
3725             }
3726           else
3727             {
3728               size = getDataSize (IC_RESULT (ic));
3729               _startLazyDPSEvaluation ();
3730               while (size--)
3731                 {
3732                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3733                   emitcode ("addc", "a,#0");
3734                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3735                 }
3736               _endLazyDPSEvaluation ();
3737             }
3738           goto release;
3739         }
3740
3741       /* if I can do an increment instead
3742          of add then GOOD for ME */
3743       if (genPlusIncr (ic) == TRUE)
3744         {
3745           emitcode (";", "did genPlusIncr");
3746           goto release;
3747         }
3748
3749     }
3750   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3751
3752   _startLazyDPSEvaluation ();
3753   while (size--)
3754     {
3755       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3756         {
3757           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3758           if (offset == 0)
3759             emitcode ("add", "a,%s",
3760                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3761           else
3762             emitcode ("addc", "a,%s",
3763                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3764         }
3765       else
3766         {
3767           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3768           {
3769               /* right is going to use ACC or we would have taken the
3770                * above branch.
3771                */
3772               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3773        TR_AP("#3");
3774               D(emitcode(";", "+ AOP_ACC special case."););
3775               emitcode("xch", "a, %s", DP2_RESULT_REG);
3776           }
3777           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3778           if (offset == 0)
3779           {
3780             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3781             {
3782          TR_AP("#4");
3783                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3784             }
3785             else
3786             {
3787                 emitcode ("add", "a,%s",
3788                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3789             }
3790           }
3791           else
3792           {
3793             emitcode ("addc", "a,%s",
3794                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3795           }
3796         }
3797       if (!pushResult)
3798         {
3799           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3800         }
3801       else
3802         {
3803           emitcode ("push", "acc");
3804         }
3805       offset++;
3806     }
3807   _endLazyDPSEvaluation ();
3808
3809   if (pushResult)
3810     {
3811       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3812
3813       size = getDataSize (IC_LEFT (ic));
3814       rSize = getDataSize (IC_RESULT (ic));
3815
3816       ADJUST_PUSHED_RESULT(size, rSize);
3817
3818       _startLazyDPSEvaluation ();
3819       while (size--)
3820         {
3821           emitcode ("pop", "acc");
3822           aopPut (AOP (IC_RESULT (ic)), "a", size);
3823         }
3824       _endLazyDPSEvaluation ();
3825     }
3826
3827   adjustArithmeticResult (ic);
3828
3829 release:
3830   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3831   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3832   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3833 }
3834
3835 /*-----------------------------------------------------------------*/
3836 /* genMinusDec :- does subtraction with deccrement if possible     */
3837 /*-----------------------------------------------------------------*/
3838 static bool
3839 genMinusDec (iCode * ic)
3840 {
3841   unsigned int icount;
3842   unsigned int size = getDataSize (IC_RESULT (ic));
3843
3844   /* will try to generate an increment */
3845   /* if the right side is not a literal
3846      we cannot */
3847   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3848     return FALSE;
3849
3850   /* if the literal value of the right hand side
3851      is greater than 4 then it is not worth it */
3852   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3853     return FALSE;
3854
3855   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3856       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3857       while (icount--) {
3858           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3859       }
3860       return TRUE;
3861   }
3862   /* if decrement 16 bits in register */
3863   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3864       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3865       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3866       (size > 1) &&
3867       (icount == 1))
3868     {
3869       symbol *tlbl;
3870       int emitTlbl;
3871       int labelRange;
3872
3873       /* If the next instruction is a goto and the goto target
3874          * is <= 5 instructions previous to this, we can generate
3875          * jumps straight to that target.
3876        */
3877       if (ic->next && ic->next->op == GOTO
3878           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3879           && labelRange <= 5)
3880         {
3881           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3882           tlbl = IC_LABEL (ic->next);
3883           emitTlbl = 0;
3884         }
3885       else
3886         {
3887           tlbl = newiTempLabel (NULL);
3888           emitTlbl = 1;
3889         }
3890
3891       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3892       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3893           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3894           IS_AOP_PREG (IC_RESULT (ic)))
3895         emitcode ("cjne", "%s,#!constbyte,!tlabel"
3896                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
3897                   ,tlbl->key + 100);
3898       else
3899         {
3900           emitcode ("mov", "a,#!constbyte",0xff);
3901           emitcode ("cjne", "a,%s,!tlabel"
3902                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3903                     ,tlbl->key + 100);
3904         }
3905       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3906       if (size > 2)
3907         {
3908           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3909               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3910               IS_AOP_PREG (IC_RESULT (ic)))
3911             emitcode ("cjne", "%s,#!constbyte,!tlabel"
3912                       ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
3913                       ,tlbl->key + 100);
3914           else
3915             {
3916               emitcode ("cjne", "a,%s,!tlabel"
3917                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3918                         ,tlbl->key + 100);
3919             }
3920           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3921         }
3922       if (size > 3)
3923         {
3924           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3925               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3926               IS_AOP_PREG (IC_RESULT (ic)))
3927             emitcode ("cjne", "%s,#!constbyte,!tlabel"
3928                       ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
3929                       ,tlbl->key + 100);
3930           else
3931             {
3932               emitcode ("cjne", "a,%s,!tlabel"
3933                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3934                         ,tlbl->key + 100);
3935             }
3936           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3937         }
3938       if (emitTlbl)
3939         {
3940           emitcode ("", "!tlabeldef", tlbl->key + 100);
3941         }
3942       return TRUE;
3943     }
3944
3945   /* if the sizes are greater than 1 then we cannot */
3946   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3947       AOP_SIZE (IC_LEFT (ic)) > 1)
3948     return FALSE;
3949
3950   /* we can if the aops of the left & result match or
3951      if they are in registers and the registers are the
3952      same */
3953   if (
3954        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3955        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3956        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3957     {
3958
3959       _startLazyDPSEvaluation ();
3960       while (icount--)
3961         {
3962           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3963         }
3964       _endLazyDPSEvaluation ();
3965
3966       return TRUE;
3967     }
3968
3969   return FALSE;
3970 }
3971
3972 /*-----------------------------------------------------------------*/
3973 /* addSign - complete with sign                                    */
3974 /*-----------------------------------------------------------------*/
3975 static void
3976 addSign (operand * result, int offset, int sign)
3977 {
3978   int size = (getDataSize (result) - offset);
3979   if (size > 0)
3980     {
3981       _startLazyDPSEvaluation();
3982       if (sign)
3983         {
3984           emitcode ("rlc", "a");
3985           emitcode ("subb", "a,acc");
3986           while (size--)
3987           {
3988             aopPut (AOP (result), "a", offset++);
3989           }
3990         }
3991       else
3992       {
3993         while (size--)
3994         {
3995           aopPut (AOP (result), zero, offset++);
3996         }
3997       }
3998       _endLazyDPSEvaluation();
3999     }
4000 }
4001
4002 /*-----------------------------------------------------------------*/
4003 /* genMinusBits - generates code for subtraction  of two bits      */
4004 /*-----------------------------------------------------------------*/
4005 static void
4006 genMinusBits (iCode * ic)
4007 {
4008   symbol *lbl = newiTempLabel (NULL);
4009
4010   D (emitcode (";", "genMinusBits "););
4011
4012   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4013     {
4014       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4015       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4016       emitcode ("cpl", "c");
4017       emitcode ("", "!tlabeldef", (lbl->key + 100));
4018       outBitC (IC_RESULT (ic));
4019     }
4020   else
4021     {
4022       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4023       emitcode ("subb", "a,acc");
4024       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4025       emitcode ("inc", "a");
4026       emitcode ("", "!tlabeldef", (lbl->key + 100));
4027       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4028       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4029     }
4030 }
4031
4032 /*-----------------------------------------------------------------*/
4033 /* genMinus - generates code for subtraction                       */
4034 /*-----------------------------------------------------------------*/
4035 static void
4036 genMinus (iCode * ic)
4037 {
4038   int size, offset = 0;
4039   int rSize;
4040   unsigned long lit = 0L;
4041   bool pushResult = FALSE;
4042
4043   D (emitcode (";", "genMinus "););
4044
4045   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4046   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
4047   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4048       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
4049     {
4050       pushResult = TRUE;
4051     }
4052   else
4053     {
4054       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4055
4056       /* special cases :- */
4057       /* if both left & right are in bit space */
4058       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4059           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4060         {
4061           genMinusBits (ic);
4062           goto release;
4063         }
4064
4065       /* if I can do an decrement instead
4066          of subtract then GOOD for ME */
4067       if (genMinusDec (ic) == TRUE)
4068         goto release;
4069
4070     }
4071
4072   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4073
4074   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4075     {
4076       CLRC;
4077     }
4078   else
4079     {
4080       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4081       lit = -(long) lit;
4082     }
4083
4084
4085   /* if literal, add a,#-lit, else normal subb */
4086   _startLazyDPSEvaluation ();
4087   while (size--)
4088     {
4089       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4090       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4091         emitcode ("subb", "a,%s",
4092                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4093       else
4094         {
4095           /* first add without previous c */
4096           if (!offset) {
4097             if (!size && lit==-1) {
4098               emitcode ("dec", "a");
4099             } else {
4100               emitcode ("add", "a,#!constbyte",
4101                         (unsigned int) (lit & 0x0FFL));
4102             }
4103           } else {
4104             emitcode ("addc", "a,#!constbyte",
4105                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4106           }
4107         }
4108
4109       if (pushResult)
4110         {
4111           emitcode ("push", "acc");
4112         }
4113       else
4114         {
4115           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4116         }
4117       offset++;
4118     }
4119   _endLazyDPSEvaluation ();
4120
4121   if (pushResult)
4122     {
4123       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4124
4125       size = getDataSize (IC_LEFT (ic));
4126       rSize = getDataSize (IC_RESULT (ic));
4127
4128       ADJUST_PUSHED_RESULT(size, rSize);
4129
4130       _startLazyDPSEvaluation ();
4131       while (size--)
4132         {
4133           emitcode ("pop", "acc");
4134           aopPut (AOP (IC_RESULT (ic)), "a", size);
4135         }
4136       _endLazyDPSEvaluation ();
4137     }
4138
4139   adjustArithmeticResult (ic);
4140
4141 release:
4142   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4143   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4144   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4145 }
4146
4147
4148 /*-----------------------------------------------------------------*/
4149 /* genMultbits :- multiplication of bits                           */
4150 /*-----------------------------------------------------------------*/
4151 static void
4152 genMultbits (operand * left,
4153              operand * right,
4154              operand * result,
4155              iCode   * ic)
4156 {
4157   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4158   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4159   aopOp(result, ic, TRUE, FALSE);
4160   outBitC (result);
4161 }
4162
4163
4164 /*-----------------------------------------------------------------*/
4165 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4166 /*-----------------------------------------------------------------*/
4167 static void
4168 genMultOneByte (operand * left,
4169                 operand * right,
4170                 operand * result,
4171                 iCode   * ic)
4172 {
4173   sym_link *opetype = operandType (result);
4174   symbol *lbl;
4175
4176
4177   /* (if two literals: the value is computed before) */
4178   /* if one literal, literal on the right */
4179   if (AOP_TYPE (left) == AOP_LIT)
4180     {
4181       operand *t = right;
4182       right = left;
4183       left = t;
4184       emitcode (";", "swapped left and right");
4185     }
4186
4187   if (SPEC_USIGN(opetype)
4188       // ignore the sign of left and right, what else can we do?
4189       || (SPEC_USIGN(operandType(left)) && 
4190           SPEC_USIGN(operandType(right)))) {
4191     // just an unsigned 8*8=8/16 multiply
4192     //emitcode (";","unsigned");
4193     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4194     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4195     emitcode ("mul", "ab");
4196    
4197     _G.accInUse++; _G.bInUse++;
4198     aopOp(result, ic, TRUE, FALSE);
4199       
4200       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4201       {
4202           // this should never happen
4203           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4204                    AOP_SIZE(result), __FILE__, lineno);
4205           exit (1);
4206       }      
4207       
4208     aopPut (AOP (result), "a", 0);
4209     _G.accInUse--; _G.bInUse--;
4210     if (AOP_SIZE(result)==2) 
4211     {
4212       aopPut (AOP (result), "b", 1);
4213     }
4214     return;
4215   }
4216
4217   // we have to do a signed multiply
4218
4219   emitcode (";", "signed");
4220   emitcode ("clr", "F0"); // reset sign flag
4221   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4222
4223   lbl=newiTempLabel(NULL);
4224   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4225   // left side is negative, 8-bit two's complement, this fails for -128
4226   emitcode ("setb", "F0"); // set sign flag
4227   emitcode ("cpl", "a");
4228   emitcode ("inc", "a");
4229
4230   emitcode ("", "!tlabeldef", lbl->key+100);
4231
4232   /* if literal */
4233   if (AOP_TYPE(right)==AOP_LIT) {
4234     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4235     /* AND literal negative */
4236     if ((int) val < 0) {
4237       emitcode ("cpl", "F0"); // complement sign flag
4238       emitcode ("mov", "b,#!constbyte", -val);
4239     } else {
4240       emitcode ("mov", "b,#!constbyte", val);
4241     }
4242   } else {
4243     lbl=newiTempLabel(NULL);
4244     emitcode ("mov", "b,a");
4245     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4246     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4247     // right side is negative, 8-bit two's complement
4248     emitcode ("cpl", "F0"); // complement sign flag
4249     emitcode ("cpl", "a");
4250     emitcode ("inc", "a");
4251     emitcode ("", "!tlabeldef", lbl->key+100);
4252   }
4253   emitcode ("mul", "ab");
4254     
4255   _G.accInUse++;_G.bInUse++;
4256   aopOp(result, ic, TRUE, FALSE);
4257     
4258   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4259   {
4260     // this should never happen
4261       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4262                AOP_SIZE(result), __FILE__, lineno);
4263       exit (1);
4264   }    
4265     
4266   lbl=newiTempLabel(NULL);
4267   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4268   // only ONE op was negative, we have to do a 8/16-bit two's complement
4269   emitcode ("cpl", "a"); // lsb
4270   if (AOP_SIZE(result)==1) {
4271     emitcode ("inc", "a");
4272   } else {
4273     emitcode ("add", "a,#1");
4274     emitcode ("xch", "a,b");
4275     emitcode ("cpl", "a"); // msb
4276     emitcode ("addc", "a,#0");
4277     emitcode ("xch", "a,b");
4278   }
4279
4280   emitcode ("", "!tlabeldef", lbl->key+100);
4281   aopPut (AOP (result), "a", 0);
4282   _G.accInUse--;_G.bInUse--;
4283   if (AOP_SIZE(result)==2) {
4284     aopPut (AOP (result), "b", 1);
4285   }
4286 }
4287
4288 /*-----------------------------------------------------------------*/
4289 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4290 /*-----------------------------------------------------------------*/
4291 static void genMultTwoByte (operand *left, operand *right, 
4292                             operand *result, iCode *ic)
4293 {
4294         sym_link *retype = getSpec(operandType(right));
4295         sym_link *letype = getSpec(operandType(left));
4296         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4297         symbol *lbl;
4298
4299         if (AOP_TYPE (left) == AOP_LIT) {
4300                 operand *t = right;
4301                 right = left;
4302                 left = t;
4303         }
4304         /* save EA bit in F1 */
4305         lbl = newiTempLabel(NULL);
4306         emitcode ("setb","F1");
4307         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4308         emitcode ("clr","F1");
4309         emitcode("","!tlabeldef",lbl->key+100);
4310
4311         /* load up MB with right */
4312         if (!umult) {
4313                 emitcode("clr","F0");
4314                 if (AOP_TYPE(right) == AOP_LIT) {
4315                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4316                         if (val < 0) {
4317                                 emitcode("setb","F0");
4318                                 val = -val;
4319                         }
4320                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4321                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4322                 } else {
4323                         lbl = newiTempLabel(NULL);
4324                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4325                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4326                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4327                         emitcode ("xch", "a,b");
4328                         emitcode ("cpl","a");
4329                         emitcode ("add", "a,#1");
4330                         emitcode ("xch", "a,b");
4331                         emitcode ("cpl", "a"); // msb
4332                         emitcode ("addc", "a,#0");
4333                         emitcode ("setb","F0");
4334                         emitcode ("","!tlabeldef",lbl->key+100);
4335                         emitcode ("mov","mb,b");
4336                         emitcode ("mov","mb,a");
4337                 }
4338         } else {
4339                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4340                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4341         }
4342         /* load up MA with left */
4343         if (!umult) {
4344                 lbl = newiTempLabel(NULL);
4345                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4346                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4347                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4348                 emitcode ("xch", "a,b");
4349                 emitcode ("cpl","a");
4350                 emitcode ("add", "a,#1");
4351                 emitcode ("xch", "a,b");
4352                 emitcode ("cpl", "a"); // msb
4353                 emitcode ("addc","a,#0");
4354                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4355                 emitcode ("setb","F0");
4356                 emitcode ("","!tlabeldef",lbl->key+100);
4357                 emitcode ("mov","ma,b");
4358                 emitcode ("mov","ma,a");
4359         } else {
4360                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4361                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4362         }
4363         /* wait for multiplication to finish */
4364         lbl = newiTempLabel(NULL);
4365         emitcode("","!tlabeldef", lbl->key+100);
4366         emitcode("mov","a,mcnt1");
4367         emitcode("anl","a,#!constbyte",0x80);
4368         emitcode("jnz","!tlabel",lbl->key+100);
4369         
4370         freeAsmop (left, NULL, ic, TRUE);
4371         freeAsmop (right, NULL, ic,TRUE);
4372         aopOp(result, ic, TRUE, FALSE);
4373
4374         /* if unsigned then simple */   
4375         if (umult) {
4376                 emitcode ("mov","a,ma");
4377                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4378                 emitcode ("mov","a,ma");
4379                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4380                 aopPut(AOP(result),"ma",1);
4381                 aopPut(AOP(result),"ma",0);
4382         } else {
4383                 emitcode("push","ma");
4384                 emitcode("push","ma");
4385                 emitcode("push","ma");
4386                 MOVA("ma");
4387                 /* negate result if needed */
4388                 lbl = newiTempLabel(NULL);      
4389                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4390                 emitcode("cpl","a");
4391                 emitcode("add","a,#1");
4392                 emitcode("","!tlabeldef", lbl->key+100);
4393                 if (AOP_TYPE(result) == AOP_ACC)
4394                 {
4395                     D(emitcode(";", "ACC special case."););
4396                     /* We know result is the only live aop, and 
4397                      * it's obviously not a DPTR2, so AP is available.
4398                      */
4399                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4400                 }
4401                 else
4402                 {
4403                     aopPut(AOP(result),"a",0);
4404                 }
4405             
4406                 emitcode("pop","acc");
4407                 lbl = newiTempLabel(NULL);      
4408                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4409                 emitcode("cpl","a");
4410                 emitcode("addc","a,#0");
4411                 emitcode("","!tlabeldef", lbl->key+100);
4412                 aopPut(AOP(result),"a",1);
4413                 emitcode("pop","acc");
4414                 if (AOP_SIZE(result) >= 3) {
4415                         lbl = newiTempLabel(NULL);      
4416                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4417                         emitcode("cpl","a");
4418                         emitcode("addc","a,#0");                        
4419                         emitcode("","!tlabeldef", lbl->key+100);
4420                         aopPut(AOP(result),"a",2);
4421                 }
4422                 emitcode("pop","acc");
4423                 if (AOP_SIZE(result) >= 4) {
4424                         lbl = newiTempLabel(NULL);      
4425                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4426                         emitcode("cpl","a");
4427                         emitcode("addc","a,#0");                        
4428                         emitcode("","!tlabeldef", lbl->key+100);
4429                         aopPut(AOP(result),"a",3);
4430                 }
4431                 if (AOP_TYPE(result) == AOP_ACC)
4432                 {
4433                     /* We stashed the result away above. */
4434                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4435                 }           
4436                 
4437         }
4438         freeAsmop (result, NULL, ic, TRUE);
4439
4440         /* restore EA bit in F1 */
4441         lbl = newiTempLabel(NULL);
4442         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4443         emitcode ("setb","EA");
4444         emitcode("","!tlabeldef",lbl->key+100);
4445         return ;
4446 }
4447
4448 /*-----------------------------------------------------------------*/
4449 /* genMult - generates code for multiplication                     */
4450 /*-----------------------------------------------------------------*/
4451 static void
4452 genMult (iCode * ic)
4453 {
4454   operand *left = IC_LEFT (ic);
4455   operand *right = IC_RIGHT (ic);
4456   operand *result = IC_RESULT (ic);
4457
4458   D (emitcode (";", "genMult "););
4459
4460   /* assign the amsops */
4461   AOP_OP_2 (ic);
4462
4463   /* special cases first */
4464   /* both are bits */
4465   if (AOP_TYPE (left) == AOP_CRY &&
4466       AOP_TYPE (right) == AOP_CRY)
4467     {
4468       genMultbits (left, right, result, ic);
4469       goto release;
4470     }
4471
4472   /* if both are of size == 1 */
4473   if (AOP_SIZE (left) == 1 &&
4474       AOP_SIZE (right) == 1)
4475     {
4476       genMultOneByte (left, right, result, ic);
4477       goto release;
4478     }
4479
4480   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4481           /* use the ds390 ARITHMETIC accel UNIT */
4482           genMultTwoByte (left, right, result, ic);
4483           return ;
4484   }
4485   /* should have been converted to function call */
4486   assert (0);
4487
4488 release:
4489   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4490   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4491   freeAsmop (result, NULL, ic, TRUE);
4492 }
4493
4494 /*-----------------------------------------------------------------*/
4495 /* genDivbits :- division of bits                                  */
4496 /*-----------------------------------------------------------------*/
4497 static void
4498 genDivbits (operand * left,
4499             operand * right,
4500             operand * result,
4501             iCode   * ic)
4502 {
4503
4504   char *l;
4505
4506   /* the result must be bit */
4507   LOAD_AB_FOR_DIV (left, right, l);
4508   emitcode ("div", "ab");
4509   emitcode ("rrc", "a");
4510   aopOp(result, ic, TRUE, FALSE);
4511     
4512   aopPut (AOP (result), "c", 0);
4513 }
4514
4515 /*-----------------------------------------------------------------*/
4516 /* genDivOneByte : 8 bit division                                  */
4517 /*-----------------------------------------------------------------*/
4518 static void
4519 genDivOneByte (operand * left,
4520                operand * right,
4521                operand * result,
4522                iCode   * ic)
4523 {
4524   sym_link *opetype = operandType (result);
4525   char *l;
4526   symbol *lbl;
4527   int size, offset;
4528
4529   offset = 1;
4530   /* signed or unsigned */
4531   if (SPEC_USIGN (opetype))
4532     {
4533         /* unsigned is easy */
4534         LOAD_AB_FOR_DIV (left, right, l);
4535         emitcode ("div", "ab");
4536
4537         _G.accInUse++;
4538         aopOp(result, ic, TRUE, FALSE);
4539         aopPut (AOP (result), "a", 0);
4540         _G.accInUse--;
4541
4542         size = AOP_SIZE (result) - 1;
4543         
4544         while (size--)
4545         {
4546             aopPut (AOP (result), zero, offset++);
4547         }
4548       return;
4549     }
4550
4551   /* signed is a little bit more difficult */
4552
4553   /* save the signs of the operands */
4554   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4555   MOVA (l);
4556   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4557   emitcode ("push", "acc");     /* save it on the stack */
4558
4559   /* now sign adjust for both left & right */
4560   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4561   MOVA (l);
4562   lbl = newiTempLabel (NULL);
4563   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4564   emitcode ("cpl", "a");
4565   emitcode ("inc", "a");
4566   emitcode ("", "!tlabeldef", (lbl->key + 100));
4567   emitcode ("mov", "b,a");
4568
4569   /* sign adjust left side */
4570   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4571   MOVA (l);
4572
4573   lbl = newiTempLabel (NULL);
4574   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4575   emitcode ("cpl", "a");
4576   emitcode ("inc", "a");
4577   emitcode ("", "!tlabeldef", (lbl->key + 100));
4578
4579   /* now the division */
4580   emitcode ("nop", "; workaround for DS80C390 div bug.");
4581   emitcode ("div", "ab");
4582   /* we are interested in the lower order
4583      only */
4584   emitcode ("mov", "b,a");
4585   lbl = newiTempLabel (NULL);
4586   emitcode ("pop", "acc");
4587   /* if there was an over flow we don't
4588      adjust the sign of the result */
4589   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4590   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4591   CLRC;
4592   emitcode ("clr", "a");
4593   emitcode ("subb", "a,b");
4594   emitcode ("mov", "b,a");
4595   emitcode ("", "!tlabeldef", (lbl->key + 100));
4596
4597   /* now we are done */
4598   _G.accInUse++;     _G.bInUse++;
4599     aopOp(result, ic, TRUE, FALSE);
4600     
4601     aopPut (AOP (result), "b", 0);
4602     
4603     size = AOP_SIZE (result) - 1;
4604     
4605     if (size > 0)
4606     {
4607       emitcode ("mov", "c,b.7");
4608       emitcode ("subb", "a,acc");
4609     }
4610     while (size--)
4611     {
4612         aopPut (AOP (result), "a", offset++);
4613     }
4614     _G.accInUse--;     _G.bInUse--;
4615
4616 }
4617
4618 /*-----------------------------------------------------------------*/
4619 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4620 /*-----------------------------------------------------------------*/
4621 static void genDivTwoByte (operand *left, operand *right, 
4622                             operand *result, iCode *ic)
4623 {
4624         sym_link *retype = getSpec(operandType(right));
4625         sym_link *letype = getSpec(operandType(left));
4626         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4627         symbol *lbl;
4628
4629         /* save EA bit in F1 */
4630         lbl = newiTempLabel(NULL);
4631         emitcode ("setb","F1");
4632         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4633         emitcode ("clr","F1");
4634         emitcode("","!tlabeldef",lbl->key+100);
4635
4636         /* load up MA with left */
4637         if (!umult) {
4638                 emitcode("clr","F0");
4639                 lbl = newiTempLabel(NULL);
4640                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4641                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4642                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4643                 emitcode ("xch", "a,b");
4644                 emitcode ("cpl","a");
4645                 emitcode ("add", "a,#1");
4646                 emitcode ("xch", "a,b");
4647                 emitcode ("cpl", "a"); // msb
4648                 emitcode ("addc","a,#0");
4649                 emitcode ("setb","F0");
4650                 emitcode ("","!tlabeldef",lbl->key+100);
4651                 emitcode ("mov","ma,b");
4652                 emitcode ("mov","ma,a");
4653         } else {
4654                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4655                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4656         }
4657
4658         /* load up MB with right */
4659         if (!umult) {
4660                 if (AOP_TYPE(right) == AOP_LIT) {
4661                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4662                         if (val < 0) {
4663                                 lbl = newiTempLabel(NULL);
4664                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4665                                 emitcode("setb","F0");
4666                                 emitcode ("","!tlabeldef",lbl->key+100);
4667                                 val = -val;
4668                         } 
4669                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4670                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4671                 } else {
4672                         lbl = newiTempLabel(NULL);
4673                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4674                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4675                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4676                         emitcode ("xch", "a,b");
4677                         emitcode ("cpl","a");
4678                         emitcode ("add", "a,#1");
4679                         emitcode ("xch", "a,b");
4680                         emitcode ("cpl", "a"); // msb
4681                         emitcode ("addc", "a,#0");
4682                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
4683                         emitcode ("setb","F0");
4684                         emitcode ("","!tlabeldef",lbl->key+100);
4685                         emitcode ("mov","mb,b");
4686                         emitcode ("mov","mb,a");
4687                 }
4688         } else {
4689                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4690                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4691         }
4692
4693         /* wait for multiplication to finish */
4694         lbl = newiTempLabel(NULL);
4695         emitcode("","!tlabeldef", lbl->key+100);
4696         emitcode("mov","a,mcnt1");
4697         emitcode("anl","a,#!constbyte",0x80);
4698         emitcode("jnz","!tlabel",lbl->key+100);
4699         
4700         freeAsmop (left, NULL, ic, TRUE);
4701         freeAsmop (right, NULL, ic,TRUE);
4702         aopOp(result, ic, TRUE, FALSE);
4703
4704         /* if unsigned then simple */   
4705         if (umult) {
4706                 aopPut(AOP(result),"ma",1);
4707                 aopPut(AOP(result),"ma",0);
4708         } else {
4709                 emitcode("push","ma");
4710                 MOVA("ma");
4711                 /* negate result if needed */
4712                 lbl = newiTempLabel(NULL);      
4713                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4714                 emitcode("cpl","a");
4715                 emitcode("add","a,#1");
4716                 emitcode("","!tlabeldef", lbl->key+100);
4717                 aopPut(AOP(result),"a",0);
4718                 emitcode("pop","acc");
4719                 lbl = newiTempLabel(NULL);      
4720                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4721                 emitcode("cpl","a");
4722                 emitcode("addc","a,#0");
4723                 emitcode("","!tlabeldef", lbl->key+100);
4724                 aopPut(AOP(result),"a",1);
4725         }
4726         freeAsmop (result, NULL, ic, TRUE);
4727         /* restore EA bit in F1 */
4728         lbl = newiTempLabel(NULL);
4729         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4730         emitcode ("setb","EA");
4731         emitcode("","!tlabeldef",lbl->key+100);
4732         return ;
4733 }
4734
4735 /*-----------------------------------------------------------------*/
4736 /* genDiv - generates code for division                            */
4737 /*-----------------------------------------------------------------*/
4738 static void
4739 genDiv (iCode * ic)
4740 {
4741   operand *left = IC_LEFT (ic);
4742   operand *right = IC_RIGHT (ic);
4743   operand *result = IC_RESULT (ic);
4744
4745   D (emitcode (";", "genDiv "););
4746
4747   /* assign the amsops */
4748   AOP_OP_2 (ic);
4749
4750   /* special cases first */
4751   /* both are bits */
4752   if (AOP_TYPE (left) == AOP_CRY &&
4753       AOP_TYPE (right) == AOP_CRY)
4754     {
4755       genDivbits (left, right, result, ic);
4756       goto release;
4757     }
4758
4759   /* if both are of size == 1 */
4760   if (AOP_SIZE (left) == 1 &&
4761       AOP_SIZE (right) == 1)
4762     {
4763       genDivOneByte (left, right, result, ic);
4764       goto release;
4765     }
4766
4767   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4768           /* use the ds390 ARITHMETIC accel UNIT */
4769           genDivTwoByte (left, right, result, ic);
4770           return ;
4771   }
4772   /* should have been converted to function call */
4773   assert (0);
4774 release:
4775   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4776   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4777   freeAsmop (result, NULL, ic, TRUE);
4778 }
4779
4780 /*-----------------------------------------------------------------*/
4781 /* genModbits :- modulus of bits                                   */
4782 /*-----------------------------------------------------------------*/
4783 static void
4784 genModbits (operand * left,
4785             operand * right,
4786             operand * result,
4787             iCode   * ic)
4788 {
4789
4790   char *l;
4791
4792   /* the result must be bit */
4793   LOAD_AB_FOR_DIV (left, right, l);
4794   emitcode ("div", "ab");
4795   emitcode ("mov", "a,b");
4796   emitcode ("rrc", "a");
4797   aopOp(result, ic, TRUE, FALSE);
4798   aopPut (AOP (result), "c", 0);
4799 }
4800
4801 /*-----------------------------------------------------------------*/
4802 /* genModOneByte : 8 bit modulus                                   */
4803 /*-----------------------------------------------------------------*/
4804 static void
4805 genModOneByte (operand * left,
4806                operand * right,
4807                operand * result,
4808                iCode   * ic)
4809 {
4810   sym_link *opetype = operandType (result);
4811   char *l;
4812   symbol *lbl;
4813
4814   /* signed or unsigned */
4815   if (SPEC_USIGN (opetype))
4816     {
4817       /* unsigned is easy */
4818       LOAD_AB_FOR_DIV (left, right, l);
4819       emitcode ("div", "ab");
4820       aopOp(result, ic, TRUE, FALSE);   
4821       aopPut (AOP (result), "b", 0);
4822       return;
4823     }
4824
4825   /* signed is a little bit more difficult */
4826
4827   /* save the signs of the operands */
4828   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4829   MOVA (l);
4830
4831   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4832   emitcode ("push", "acc");     /* save it on the stack */
4833
4834   /* now sign adjust for both left & right */
4835   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4836   MOVA (l);
4837
4838   lbl = newiTempLabel (NULL);
4839   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4840   emitcode ("cpl", "a");
4841   emitcode ("inc", "a");
4842   emitcode ("", "!tlabeldef", (lbl->key + 100));
4843   emitcode ("mov", "b,a");
4844
4845   /* sign adjust left side */
4846   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4847   MOVA (l);
4848
4849   lbl = newiTempLabel (NULL);
4850   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4851   emitcode ("cpl", "a");
4852   emitcode ("inc", "a");
4853   emitcode ("", "!tlabeldef", (lbl->key + 100));
4854
4855   /* now the multiplication */
4856   emitcode ("nop", "; workaround for DS80C390 div bug.");
4857   emitcode ("div", "ab");
4858   /* we are interested in the lower order
4859      only */
4860   lbl = newiTempLabel (NULL);
4861   emitcode ("pop", "acc");
4862   /* if there was an over flow we don't
4863      adjust the sign of the result */
4864   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4865   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4866   CLRC;
4867   emitcode ("clr", "a");
4868   emitcode ("subb", "a,b");
4869   emitcode ("mov", "b,a");
4870   emitcode ("", "!tlabeldef", (lbl->key + 100));
4871   
4872   _G.bInUse++;
4873   /* now we are done */
4874   aopOp(result, ic, TRUE, FALSE);    
4875   aopPut (AOP (result), "b", 0);
4876   _G.bInUse--;
4877
4878 }
4879
4880 /*-----------------------------------------------------------------*/
4881 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4882 /*-----------------------------------------------------------------*/
4883 static void genModTwoByte (operand *left, operand *right, 
4884                             operand *result, iCode *ic)
4885 {
4886         sym_link *retype = getSpec(operandType(right));
4887         sym_link *letype = getSpec(operandType(left));
4888         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4889         symbol *lbl;
4890
4891         /* load up MA with left */
4892         /* save EA bit in F1 */
4893         lbl = newiTempLabel(NULL);
4894         emitcode ("setb","F1");
4895         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4896         emitcode ("clr","F1");
4897         emitcode("","!tlabeldef",lbl->key+100);
4898
4899         if (!umult) {
4900                 lbl = newiTempLabel(NULL);
4901                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4902                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4903                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4904                 emitcode ("xch", "a,b");
4905                 emitcode ("cpl","a");
4906                 emitcode ("add", "a,#1");
4907                 emitcode ("xch", "a,b");
4908                 emitcode ("cpl", "a"); // msb
4909                 emitcode ("addc","a,#0");
4910                 emitcode ("","!tlabeldef",lbl->key+100);
4911                 emitcode ("mov","ma,b");
4912                 emitcode ("mov","ma,a");
4913         } else {
4914                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4915                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4916         }
4917
4918         /* load up MB with right */
4919         if (!umult) {
4920                 if (AOP_TYPE(right) == AOP_LIT) {
4921                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4922                         if (val < 0) {
4923                                 val = -val;
4924                         } 
4925                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4926                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4927                 } else {
4928                         lbl = newiTempLabel(NULL);
4929                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4930                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4931                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4932                         emitcode ("xch", "a,b");
4933                         emitcode ("cpl","a");
4934                         emitcode ("add", "a,#1");
4935                         emitcode ("xch", "a,b");
4936                         emitcode ("cpl", "a"); // msb
4937                         emitcode ("addc", "a,#0");
4938                         emitcode ("","!tlabeldef",lbl->key+100);
4939                         emitcode ("mov","mb,b");
4940                         emitcode ("mov","mb,a");
4941                 }
4942         } else {
4943                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4944                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4945         }
4946
4947         /* wait for multiplication to finish */
4948         lbl = newiTempLabel(NULL);
4949         emitcode("","!tlabeldef", lbl->key+100);
4950         emitcode("mov","a,mcnt1");
4951         emitcode("anl","a,#!constbyte",0x80);
4952         emitcode("jnz","!tlabel",lbl->key+100);
4953         
4954         freeAsmop (left, NULL, ic, TRUE);
4955         freeAsmop (right, NULL, ic,TRUE);
4956         aopOp(result, ic, TRUE, FALSE);
4957
4958         aopPut(AOP(result),"mb",1);
4959         aopPut(AOP(result),"mb",0);
4960         freeAsmop (result, NULL, ic, TRUE);
4961
4962         /* restore EA bit in F1 */
4963         lbl = newiTempLabel(NULL);
4964         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4965         emitcode ("setb","EA");
4966         emitcode("","!tlabeldef",lbl->key+100);
4967         return ;
4968 }
4969
4970 /*-----------------------------------------------------------------*/
4971 /* genMod - generates code for division                            */
4972 /*-----------------------------------------------------------------*/
4973 static void
4974 genMod (iCode * ic)
4975 {
4976   operand *left = IC_LEFT (ic);
4977   operand *right = IC_RIGHT (ic);
4978   operand *result = IC_RESULT (ic);
4979
4980   D (emitcode (";", "genMod "); );
4981
4982   /* assign the amsops */
4983   AOP_OP_2 (ic);
4984
4985   /* special cases first */
4986   /* both are bits */
4987   if (AOP_TYPE (left) == AOP_CRY &&
4988       AOP_TYPE (right) == AOP_CRY)
4989     {
4990       genModbits (left, right, result, ic);
4991       goto release;
4992     }
4993
4994   /* if both are of size == 1 */
4995   if (AOP_SIZE (left) == 1 &&
4996       AOP_SIZE (right) == 1)
4997     {
4998       genModOneByte (left, right, result, ic);
4999       goto release;
5000     }
5001
5002   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5003           /* use the ds390 ARITHMETIC accel UNIT */
5004           genModTwoByte (left, right, result, ic);
5005           return ;
5006   }
5007
5008   /* should have been converted to function call */
5009   assert (0);
5010
5011 release:
5012   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5013   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5014   freeAsmop (result, NULL, ic, TRUE);
5015 }
5016
5017 /*-----------------------------------------------------------------*/
5018 /* genIfxJump :- will create a jump depending on the ifx           */
5019 /*-----------------------------------------------------------------*/
5020 static void
5021 genIfxJump (iCode * ic, char *jval)
5022 {
5023   symbol *jlbl;
5024   symbol *tlbl = newiTempLabel (NULL);
5025   char *inst;
5026
5027   D (emitcode (";", "genIfxJump ");
5028     );
5029
5030   /* if true label then we jump if condition
5031      supplied is true */
5032   if (IC_TRUE (ic))
5033     {
5034       jlbl = IC_TRUE (ic);
5035       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5036                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5037     }
5038   else
5039     {
5040       /* false label is present */
5041       jlbl = IC_FALSE (ic);
5042       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5043                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5044     }
5045   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5046     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5047   else
5048     emitcode (inst, "!tlabel", tlbl->key + 100);
5049   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5050   emitcode ("", "!tlabeldef", tlbl->key + 100);
5051
5052   /* mark the icode as generated */
5053   ic->generated = 1;
5054 }
5055
5056 /*-----------------------------------------------------------------*/
5057 /* genCmp :- greater or less than comparison                       */
5058 /*-----------------------------------------------------------------*/
5059 static void
5060 genCmp (operand * left, operand * right,
5061         iCode * ic, iCode * ifx, int sign)
5062 {
5063   int size, offset = 0;
5064   unsigned long lit = 0L;
5065   operand *result;
5066
5067   D (emitcode (";", "genCmp");
5068     );
5069
5070   result = IC_RESULT (ic);
5071
5072   /* if left & right are bit variables */
5073   if (AOP_TYPE (left) == AOP_CRY &&
5074       AOP_TYPE (right) == AOP_CRY)
5075     {
5076       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5077       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5078     }
5079   else
5080     {
5081       /* subtract right from left if at the
5082          end the carry flag is set then we know that
5083          left is greater than right */
5084       size = max (AOP_SIZE (left), AOP_SIZE (right));
5085
5086       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5087       if ((size == 1) && !sign &&
5088           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5089         {
5090           symbol *lbl = newiTempLabel (NULL);
5091           emitcode ("cjne", "%s,%s,!tlabel",
5092                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5093                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5094                     lbl->key + 100);
5095           emitcode ("", "!tlabeldef", lbl->key + 100);
5096         }
5097       else
5098         {
5099           if (AOP_TYPE (right) == AOP_LIT)
5100             {
5101               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5102               /* optimize if(x < 0) or if(x >= 0) */
5103               if (lit == 0L)
5104                 {
5105                   if (!sign)
5106                     {
5107                       CLRC;
5108                     }
5109                   else
5110                     {
5111                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5112
5113                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5114                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5115
5116                       aopOp (result, ic, FALSE, FALSE);
5117
5118                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5119                         {
5120                           freeAsmop (result, NULL, ic, TRUE);
5121                           genIfxJump (ifx, "acc.7");
5122                           return;
5123                         }
5124                       else
5125                         {
5126                           emitcode ("rlc", "a");
5127                         }
5128                       goto release_freedLR;
5129                     }
5130                   goto release;
5131                 }
5132             }
5133           CLRC;
5134           while (size--)
5135             {
5136               //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5137               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5138               //emitcode (";", "genCmp #2");
5139               if (sign && (size == 0))
5140                 {
5141                     //emitcode (";", "genCmp #3");
5142                   emitcode ("xrl", "a,#!constbyte",0x80);
5143                   if (AOP_TYPE (right) == AOP_LIT)
5144                     {
5145                       unsigned long lit = (unsigned long)
5146                       floatFromVal (AOP (right)->aopu.aop_lit);
5147                       //emitcode (";", "genCmp #3.1");
5148                       emitcode ("subb", "a,#!constbyte",
5149                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5150                     }
5151                   else
5152                     {
5153                       //emitcode (";", "genCmp #3.2");
5154                       if (AOP_NEEDSACC (right))
5155                         {
5156                           emitcode ("push", "acc");
5157                         }
5158                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5159                                                        FALSE, FALSE, FALSE));
5160                       emitcode ("xrl", "b,#!constbyte",0x80);
5161                       if (AOP_NEEDSACC (right))
5162                         {
5163                           emitcode ("pop", "acc");
5164                         }
5165                       emitcode ("subb", "a,b");
5166                     }
5167                 }
5168               else
5169                 {
5170                   const char *s;
5171
5172                   //emitcode (";", "genCmp #4");
5173                   if (AOP_NEEDSACC (right))
5174                     {
5175                       /* Yuck!! */
5176                       //emitcode (";", "genCmp #4.1");
5177                       emitcode ("xch", "a, b");
5178                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5179                       emitcode ("xch", "a, b");
5180                       s = "b";
5181                     }
5182                   else
5183                     {
5184                       //emitcode (";", "genCmp #4.2");
5185                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5186                     }
5187
5188                   emitcode ("subb", "a,%s", s);
5189                 }
5190             }
5191         }
5192     }
5193
5194 release:
5195 /* Don't need the left & right operands any more; do need the result. */
5196   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5197   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5198
5199   aopOp (result, ic, FALSE, FALSE);
5200
5201 release_freedLR:
5202
5203   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5204     {
5205       outBitC (result);
5206     }
5207   else
5208     {
5209       /* if the result is used in the next
5210          ifx conditional branch then generate
5211          code a little differently */
5212       if (ifx)
5213         {
5214           genIfxJump (ifx, "c");
5215         }
5216       else
5217         {
5218           outBitC (result);
5219         }
5220       /* leave the result in acc */
5221     }
5222   freeAsmop (result, NULL, ic, TRUE);
5223 }
5224
5225 /*-----------------------------------------------------------------*/
5226 /* genCmpGt :- greater than comparison                             */
5227 /*-----------------------------------------------------------------*/
5228 static void
5229 genCmpGt (iCode * ic, iCode * ifx)
5230 {
5231   operand *left, *right;
5232   sym_link *letype, *retype;
5233   int sign;
5234
5235   D (emitcode (";", "genCmpGt ");
5236     );
5237
5238   left = IC_LEFT (ic);
5239   right = IC_RIGHT (ic);
5240
5241   letype = getSpec (operandType (left));
5242   retype = getSpec (operandType (right));
5243   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5244
5245   /* assign the left & right amsops */
5246   AOP_OP_2 (ic);
5247
5248   genCmp (right, left, ic, ifx, sign);
5249 }
5250
5251 /*-----------------------------------------------------------------*/
5252 /* genCmpLt - less than comparisons                                */
5253 /*-----------------------------------------------------------------*/
5254 static void
5255 genCmpLt (iCode * ic, iCode * ifx)
5256 {
5257   operand *left, *right;
5258   sym_link *letype, *retype;
5259   int sign;
5260
5261   D (emitcode (";", "genCmpLt "););
5262
5263   left = IC_LEFT (ic);
5264   right = IC_RIGHT (ic);
5265
5266   letype = getSpec (operandType (left));
5267   retype = getSpec (operandType (right));
5268   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5269
5270   /* assign the left & right amsops */
5271   AOP_OP_2 (ic);
5272
5273   genCmp (left, right, ic, ifx, sign);
5274 }
5275
5276 /*-----------------------------------------------------------------*/
5277 /* gencjneshort - compare and jump if not equal                    */
5278 /*-----------------------------------------------------------------*/
5279 static void
5280 gencjneshort (operand * left, operand * right, symbol * lbl)
5281 {
5282   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5283   int offset = 0;
5284   unsigned long lit = 0L;
5285
5286   D (emitcode (";", "gencjneshort");
5287     );
5288
5289   /* if the left side is a literal or
5290      if the right is in a pointer register and left
5291      is not */
5292   if ((AOP_TYPE (left) == AOP_LIT) ||
5293       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5294     {
5295       operand *t = right;
5296       right = left;
5297       left = t;
5298     }
5299
5300   if (AOP_TYPE (right) == AOP_LIT)
5301     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5302
5303   if (opIsGptr (left) || opIsGptr (right))
5304     {
5305       /* We are comparing a generic pointer to something.
5306        * Exclude the generic type byte from the comparison.
5307        */
5308       size--;
5309       D (emitcode (";", "cjneshort: generic ptr special case.");
5310         )
5311     }
5312
5313
5314   /* if the right side is a literal then anything goes */
5315   if (AOP_TYPE (right) == AOP_LIT &&
5316       AOP_TYPE (left) != AOP_DIR)
5317     {
5318       while (size--)
5319         {
5320           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5321           MOVA (l);
5322           emitcode ("cjne", "a,%s,!tlabel",
5323                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5324                     lbl->key + 100);
5325           offset++;
5326         }
5327     }
5328
5329   /* if the right side is in a register or in direct space or
5330      if the left is a pointer register & right is not */
5331   else if (AOP_TYPE (right) == AOP_REG ||
5332            AOP_TYPE (right) == AOP_DIR ||
5333            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5334            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5335     {
5336       while (size--)
5337         {
5338           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5339           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5340               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5341             emitcode ("jnz", "!tlabel", lbl->key + 100);
5342           else
5343             emitcode ("cjne", "a,%s,!tlabel",
5344                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5345                       lbl->key + 100);
5346           offset++;
5347         }
5348     }
5349   else
5350     {
5351       /* right is a pointer reg need both a & b */
5352       while (size--)
5353         {
5354           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5355           if (strcmp (l, "b"))
5356             emitcode ("mov", "b,%s", l);
5357           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5358           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5359           offset++;
5360         }
5361     }
5362 }
5363
5364 /*-----------------------------------------------------------------*/
5365 /* gencjne - compare and jump if not equal                         */
5366 /*-----------------------------------------------------------------*/
5367 static void
5368 gencjne (operand * left, operand * right, symbol * lbl)
5369 {
5370   symbol *tlbl = newiTempLabel (NULL);
5371
5372   D (emitcode (";", "gencjne");
5373     );
5374
5375   gencjneshort (left, right, lbl);
5376
5377   emitcode ("mov", "a,%s", one);
5378   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5379   emitcode ("", "!tlabeldef", lbl->key + 100);
5380   emitcode ("clr", "a");
5381   emitcode ("", "!tlabeldef", tlbl->key + 100);
5382 }
5383
5384 /*-----------------------------------------------------------------*/
5385 /* genCmpEq - generates code for equal to                          */
5386 /*-----------------------------------------------------------------*/
5387 static void
5388 genCmpEq (iCode * ic, iCode * ifx)
5389 {
5390   operand *left, *right, *result;
5391
5392   D (emitcode (";", "genCmpEq ");
5393     );
5394
5395   AOP_OP_2 (ic);
5396   AOP_SET_LOCALS (ic);
5397
5398   /* if literal, literal on the right or
5399      if the right is in a pointer register and left
5400      is not */
5401   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5402       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5403     {
5404       operand *t = IC_RIGHT (ic);
5405       IC_RIGHT (ic) = IC_LEFT (ic);
5406       IC_LEFT (ic) = t;
5407     }
5408
5409   if (ifx &&                    /* !AOP_SIZE(result) */
5410       OP_SYMBOL (result) &&
5411       OP_SYMBOL (result)->regType == REG_CND)
5412     {
5413       symbol *tlbl;
5414       /* if they are both bit variables */
5415       if (AOP_TYPE (left) == AOP_CRY &&
5416           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5417         {
5418           if (AOP_TYPE (right) == AOP_LIT)
5419             {
5420               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5421               if (lit == 0L)
5422                 {
5423                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5424                   emitcode ("cpl", "c");
5425                 }
5426               else if (lit == 1L)
5427                 {
5428                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5429                 }
5430               else
5431                 {
5432                   emitcode ("clr", "c");
5433                 }
5434               /* AOP_TYPE(right) == AOP_CRY */
5435             }
5436           else
5437             {
5438               symbol *lbl = newiTempLabel (NULL);
5439               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5440               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5441               emitcode ("cpl", "c");
5442               emitcode ("", "!tlabeldef", (lbl->key + 100));
5443             }
5444           /* if true label then we jump if condition
5445              supplied is true */
5446           tlbl = newiTempLabel (NULL);
5447           if (IC_TRUE (ifx))
5448             {
5449               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5450               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5451             }
5452           else
5453             {
5454               emitcode ("jc", "!tlabel", tlbl->key + 100);
5455               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5456             }
5457           emitcode ("", "!tlabeldef", tlbl->key + 100);
5458         }
5459       else
5460         {
5461           tlbl = newiTempLabel (NULL);
5462           gencjneshort (left, right, tlbl);
5463           if (IC_TRUE (ifx))
5464             {
5465               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5466               emitcode ("", "!tlabeldef", tlbl->key + 100);
5467             }
5468           else
5469             {
5470               symbol *lbl = newiTempLabel (NULL);
5471               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5472               emitcode ("", "!tlabeldef", tlbl->key + 100);
5473               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5474               emitcode ("", "!tlabeldef", lbl->key + 100);
5475             }
5476         }
5477       /* mark the icode as generated */
5478       ifx->generated = 1;
5479
5480       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5481       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5482       return;
5483     }
5484
5485   /* if they are both bit variables */
5486   if (AOP_TYPE (left) == AOP_CRY &&
5487       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5488     {
5489       if (AOP_TYPE (right) == AOP_LIT)
5490         {
5491           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5492           if (lit == 0L)
5493             {
5494               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5495               emitcode ("cpl", "c");
5496             }
5497           else if (lit == 1L)
5498             {
5499               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5500             }
5501           else
5502             {
5503               emitcode ("clr", "c");
5504             }
5505           /* AOP_TYPE(right) == AOP_CRY */
5506         }
5507       else
5508         {
5509           symbol *lbl = newiTempLabel (NULL);
5510           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5511           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5512           emitcode ("cpl", "c");
5513           emitcode ("", "!tlabeldef", (lbl->key + 100));
5514         }
5515
5516       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5517       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5518
5519       aopOp (result, ic, TRUE, FALSE);
5520
5521       /* c = 1 if egal */
5522       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5523         {
5524           outBitC (result);
5525           goto release;
5526         }
5527       if (ifx)
5528         {
5529           genIfxJump (ifx, "c");
5530           goto release;
5531         }
5532       /* if the result is used in an arithmetic operation
5533          then put the result in place */
5534       outBitC (result);
5535     }
5536   else
5537     {
5538       gencjne (left, right, newiTempLabel (NULL));
5539
5540       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5541       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5542
5543       aopOp (result, ic, TRUE, FALSE);
5544
5545       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5546         {
5547           aopPut (AOP (result), "a", 0);
5548           goto release;
5549         }
5550       if (ifx)
5551         {
5552           genIfxJump (ifx, "a");
5553           goto release;
5554         }
5555       /* if the result is used in an arithmetic operation
5556          then put the result in place */
5557       if (AOP_TYPE (result) != AOP_CRY)
5558         outAcc (result);
5559       /* leave the result in acc */
5560     }
5561
5562 release:
5563   freeAsmop (result, NULL, ic, TRUE);
5564 }
5565
5566 /*-----------------------------------------------------------------*/
5567 /* ifxForOp - returns the icode containing the ifx for operand     */
5568 /*-----------------------------------------------------------------*/
5569 static iCode *
5570 ifxForOp (operand * op, iCode * ic)
5571 {
5572   /* if true symbol then needs to be assigned */
5573   if (IS_TRUE_SYMOP (op))
5574     return NULL;
5575
5576   /* if this has register type condition and
5577      the next instruction is ifx with the same operand
5578      and live to of the operand is upto the ifx only then */
5579   if (ic->next &&
5580       ic->next->op == IFX &&
5581       IC_COND (ic->next)->key == op->key &&
5582       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5583     return ic->next;
5584
5585   return NULL;
5586 }
5587 /*-----------------------------------------------------------------*/
5588 /* hasInc - operand is incremented before any other use            */
5589 /*-----------------------------------------------------------------*/
5590 static iCode *
5591 hasInc (operand *op, iCode *ic, int osize)
5592 {
5593   sym_link *type = operandType(op);
5594   sym_link *retype = getSpec (type);
5595   iCode *lic = ic->next;
5596   int isize ;
5597   
5598   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5599   if (!IS_SYMOP(op)) return NULL;
5600
5601   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5602   if (IS_AGGREGATE(type->next)) return NULL;
5603   if (osize != (isize = getSize(type->next))) return NULL;
5604
5605   while (lic) {
5606       /* if operand of the form op = op + <sizeof *op> */
5607       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5608           isOperandEqual(IC_RESULT(lic),op) && 
5609           isOperandLiteral(IC_RIGHT(lic)) &&
5610           operandLitValue(IC_RIGHT(lic)) == isize) {
5611           return lic;
5612       }
5613       /* if the operand used or deffed */
5614       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5615           return NULL;
5616       }
5617       /* if GOTO or IFX */
5618       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5619       lic = lic->next;
5620   }
5621   return NULL;
5622 }
5623
5624 /*-----------------------------------------------------------------*/
5625 /* genAndOp - for && operation                                     */
5626 /*-----------------------------------------------------------------*/
5627 static void
5628 genAndOp (iCode * ic)
5629 {
5630   operand *left, *right, *result;
5631   symbol *tlbl;
5632
5633   D (emitcode (";", "genAndOp "););
5634
5635   /* note here that && operations that are in an
5636      if statement are taken away by backPatchLabels
5637      only those used in arthmetic operations remain */
5638   AOP_OP_2 (ic);
5639   AOP_SET_LOCALS (ic);
5640
5641   /* if both are bit variables */
5642   if (AOP_TYPE (left) == AOP_CRY &&
5643       AOP_TYPE (right) == AOP_CRY)
5644     {
5645       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5646       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5647       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5648       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5649   
5650       aopOp (result,ic,FALSE, FALSE);
5651       outBitC (result);
5652     }
5653   else
5654     {
5655       tlbl = newiTempLabel (NULL);
5656       toBoolean (left);
5657       emitcode ("jz", "!tlabel", tlbl->key + 100);
5658       toBoolean (right);
5659       emitcode ("", "!tlabeldef", tlbl->key + 100);
5660       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5661       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5662   
5663       aopOp (result,ic,FALSE, FALSE);
5664       outBitAcc (result);
5665     }
5666     freeAsmop (result, NULL, ic, TRUE);
5667 }
5668
5669
5670 /*-----------------------------------------------------------------*/
5671 /* genOrOp - for || operation                                      */
5672 /*-----------------------------------------------------------------*/
5673 static void
5674 genOrOp (iCode * ic)
5675 {
5676   operand *left, *right, *result;
5677   symbol *tlbl;
5678
5679   D (emitcode (";", "genOrOp "););
5680
5681   /* note here that || operations that are in an
5682      if statement are taken away by backPatchLabels
5683      only those used in arthmetic operations remain */
5684   AOP_OP_2 (ic);
5685   AOP_SET_LOCALS (ic);
5686
5687   /* if both are bit variables */
5688   if (AOP_TYPE (left) == AOP_CRY &&
5689       AOP_TYPE (right) == AOP_CRY)
5690     {
5691       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5692       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5693       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5694       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5695   
5696       aopOp (result,ic,FALSE, FALSE);
5697       
5698       outBitC (result);
5699     }
5700   else
5701     {
5702       tlbl = newiTempLabel (NULL);
5703       toBoolean (left);
5704       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5705       toBoolean (right);
5706       emitcode ("", "!tlabeldef", tlbl->key + 100);
5707       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5708       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5709   
5710       aopOp (result,ic,FALSE, FALSE);
5711       
5712       outBitAcc (result);
5713     }
5714
5715   freeAsmop (result, NULL, ic, TRUE);
5716 }
5717
5718 /*-----------------------------------------------------------------*/
5719 /* isLiteralBit - test if lit == 2^n                               */
5720 /*-----------------------------------------------------------------*/
5721 static int
5722 isLiteralBit (unsigned long lit)
5723 {
5724   unsigned long pw[32] =
5725   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5726    0x100L, 0x200L, 0x400L, 0x800L,
5727    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5728    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5729    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5730    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5731    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5732   int idx;
5733
5734   for (idx = 0; idx < 32; idx++)
5735     if (lit == pw[idx])
5736       return idx + 1;
5737   return 0;
5738 }
5739
5740 /*-----------------------------------------------------------------*/
5741 /* continueIfTrue -                                                */
5742 /*-----------------------------------------------------------------*/
5743 static void
5744 continueIfTrue (iCode * ic)
5745 {
5746   if (IC_TRUE (ic))
5747     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5748   ic->generated = 1;
5749 }
5750
5751 /*-----------------------------------------------------------------*/
5752 /* jmpIfTrue -                                                     */
5753 /*-----------------------------------------------------------------*/
5754 static void
5755 jumpIfTrue (iCode * ic)
5756 {
5757   if (!IC_TRUE (ic))
5758     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5759   ic->generated = 1;
5760 }
5761
5762 /*-----------------------------------------------------------------*/
5763 /* jmpTrueOrFalse -                                                */
5764 /*-----------------------------------------------------------------*/
5765 static void
5766 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5767 {
5768   // ugly but optimized by peephole
5769   if (IC_TRUE (ic))
5770     {
5771       symbol *nlbl = newiTempLabel (NULL);
5772       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5773       emitcode ("", "!tlabeldef", tlbl->key + 100);
5774       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5775       emitcode ("", "!tlabeldef", nlbl->key + 100);
5776     }
5777   else
5778     {
5779       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5780       emitcode ("", "!tlabeldef", tlbl->key + 100);
5781     }
5782   ic->generated = 1;
5783 }
5784
5785 // Generate code to perform a bit-wise logic operation
5786 // on two operands in far space (assumed to already have been 
5787 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5788 // in far space. This requires pushing the result on the stack
5789 // then popping it into the result.
5790 static void
5791 genFarFarLogicOp(iCode *ic, char *logicOp)
5792 {
5793       int size, resultSize, compSize;
5794       int offset = 0;
5795       
5796       TR_AP("#5");
5797       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5798       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5799                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5800       
5801       _startLazyDPSEvaluation();
5802       for (size = compSize; (size--); offset++)
5803       {
5804           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5805           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5806           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5807           
5808           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5809           emitcode ("push", "acc");
5810       }
5811       _endLazyDPSEvaluation();
5812      
5813       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5814       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5815       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5816      
5817       resultSize = AOP_SIZE(IC_RESULT(ic));
5818
5819       ADJUST_PUSHED_RESULT(compSize, resultSize);
5820
5821       _startLazyDPSEvaluation();
5822       while (compSize--)
5823       {
5824           emitcode ("pop", "acc");
5825           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5826       }
5827       _endLazyDPSEvaluation();
5828       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5829 }
5830
5831
5832 /*-----------------------------------------------------------------*/
5833 /* genAnd  - code for and                                          */
5834 /*-----------------------------------------------------------------*/
5835 static void
5836 genAnd (iCode * ic, iCode * ifx)
5837 {
5838   operand *left, *right, *result;
5839   int size, offset = 0;
5840   unsigned long lit = 0L;
5841   int bytelit = 0;
5842   char buffer[10];
5843   bool pushResult;
5844
5845   D (emitcode (";", "genAnd "););
5846
5847   AOP_OP_3_NOFATAL (ic, pushResult);
5848   AOP_SET_LOCALS (ic);
5849
5850   if (pushResult)
5851   {
5852       genFarFarLogicOp(ic, "anl");
5853       return;
5854   }  
5855
5856 #ifdef DEBUG_TYPE
5857   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5858             AOP_TYPE (result),
5859             AOP_TYPE (left), AOP_TYPE (right));
5860   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5861             AOP_SIZE (result),
5862             AOP_SIZE (left), AOP_SIZE (right));
5863 #endif
5864
5865   /* if left is a literal & right is not then exchange them */
5866   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5867 #ifdef LOGIC_OPS_BROKEN      
5868     ||  AOP_NEEDSACC (left)
5869 #endif
5870     )
5871     {
5872       operand *tmp = right;
5873       right = left;
5874       left = tmp;
5875     }
5876
5877   /* if result = right then exchange them */
5878   if (sameRegs (AOP (result), AOP (right)))
5879     {
5880       operand *tmp = right;
5881       right = left;
5882       left = tmp;
5883     }
5884
5885   /* if right is bit then exchange them */
5886   if (AOP_TYPE (right) == AOP_CRY &&
5887       AOP_TYPE (left) != AOP_CRY)
5888     {
5889       operand *tmp = right;
5890       right = left;
5891       left = tmp;
5892     }
5893   if (AOP_TYPE (right) == AOP_LIT)
5894     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5895
5896   size = AOP_SIZE (result);
5897
5898   // if(bit & yy)
5899   // result = bit & yy;
5900   if (AOP_TYPE (left) == AOP_CRY)
5901     {
5902       // c = bit & literal;
5903       if (AOP_TYPE (right) == AOP_LIT)
5904         {
5905           if (lit & 1)
5906             {
5907               if (size && sameRegs (AOP (result), AOP (left)))
5908                 // no change
5909                 goto release;
5910               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5911             }
5912           else
5913             {
5914               // bit(result) = 0;
5915               if (size && (AOP_TYPE (result) == AOP_CRY))
5916                 {
5917                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5918                   goto release;
5919                 }
5920               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5921                 {
5922                   jumpIfTrue (ifx);
5923                   goto release;
5924                 }
5925               emitcode ("clr", "c");
5926             }
5927         }
5928       else
5929         {
5930           if (AOP_TYPE (right) == AOP_CRY)
5931             {
5932               // c = bit & bit;
5933               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5934               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5935             }
5936           else
5937             {
5938               // c = bit & val;
5939               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5940               // c = lsb
5941               emitcode ("rrc", "a");
5942               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5943             }
5944         }
5945       // bit = c
5946       // val = c
5947       if (size)
5948         outBitC (result);
5949       // if(bit & ...)
5950       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5951         genIfxJump (ifx, "c");
5952       goto release;
5953     }
5954
5955   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5956   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5957   if ((AOP_TYPE (right) == AOP_LIT) &&
5958       (AOP_TYPE (result) == AOP_CRY) &&
5959       (AOP_TYPE (left) != AOP_CRY))
5960     {
5961       int posbit = isLiteralBit (lit);
5962       /* left &  2^n */
5963       if (posbit)
5964         {
5965           posbit--;
5966           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5967           // bit = left & 2^n
5968           if (size)
5969             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5970           // if(left &  2^n)
5971           else
5972             {
5973               if (ifx)
5974                 {
5975                   sprintf (buffer, "acc.%d", posbit & 0x07);
5976                   genIfxJump (ifx, buffer);
5977                 }
5978               goto release;
5979             }
5980         }
5981       else
5982         {
5983           symbol *tlbl = newiTempLabel (NULL);
5984           int sizel = AOP_SIZE (left);
5985           if (size)
5986             emitcode ("setb", "c");
5987           while (sizel--)
5988             {
5989               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5990                 {
5991                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5992                   // byte ==  2^n ?
5993                   if ((posbit = isLiteralBit (bytelit)) != 0)
5994                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
5995                   else
5996                     {
5997                       if (bytelit != 0x0FFL)
5998                         emitcode ("anl", "a,%s",
5999                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
6000                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
6001                     }
6002                 }
6003               offset++;
6004             }
6005           // bit = left & literal
6006           if (size)
6007             {
6008               emitcode ("clr", "c");
6009               emitcode ("", "!tlabeldef", tlbl->key + 100);
6010             }
6011           // if(left & literal)
6012           else
6013             {
6014               if (ifx)
6015                 jmpTrueOrFalse (ifx, tlbl);
6016               goto release;
6017             }
6018         }
6019       outBitC (result);
6020       goto release;
6021     }
6022
6023   /* if left is same as result */
6024   if (sameRegs (AOP (result), AOP (left)))
6025     {
6026       for (; size--; offset++)
6027         {
6028           if (AOP_TYPE (right) == AOP_LIT)
6029             {
6030               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6031                 continue;
6032               else if (bytelit == 0)
6033                 aopPut (AOP (result), zero, offset);
6034               else if (IS_AOP_PREG (result))
6035                 {
6036                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6037                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6038                   aopPut (AOP (result), "a", offset);
6039                 }
6040               else
6041                 emitcode ("anl", "%s,%s",
6042                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6043                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6044             }
6045           else
6046             {
6047               if (AOP_TYPE (left) == AOP_ACC)
6048                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6049               else
6050                 {
6051                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6052                   if (IS_AOP_PREG (result))
6053                     {
6054                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6055                       aopPut (AOP (result), "a", offset);
6056
6057                     }
6058                   else
6059                     emitcode ("anl", "%s,a",
6060                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6061                 }
6062             }
6063         }
6064     }
6065   else
6066     {
6067       // left & result in different registers
6068       if (AOP_TYPE (result) == AOP_CRY)
6069         {
6070           // result = bit
6071           // if(size), result in bit
6072           // if(!size && ifx), conditional oper: if(left & right)
6073           symbol *tlbl = newiTempLabel (NULL);
6074           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6075           if (size)
6076             emitcode ("setb", "c");
6077           while (sizer--)
6078             {
6079               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6080                 emitcode ("anl", "a,%s",
6081                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6082               } else {
6083                 if (AOP_TYPE(left)==AOP_ACC) {
6084                   emitcode("mov", "b,a");
6085                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6086                   emitcode("anl", "a,b");
6087                 }else {
6088                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6089                   emitcode ("anl", "a,%s",
6090                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6091                 }
6092               }
6093               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6094               offset++;
6095             }
6096           if (size)
6097             {
6098               CLRC;
6099               emitcode ("", "!tlabeldef", tlbl->key + 100);
6100               outBitC (result);
6101             }
6102           else if (ifx)
6103             jmpTrueOrFalse (ifx, tlbl);
6104         }
6105       else
6106         {
6107           for (; (size--); offset++)
6108             {
6109               // normal case
6110               // result = left & right
6111               if (AOP_TYPE (right) == AOP_LIT)
6112                 {
6113                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6114                     {
6115                       aopPut (AOP (result),
6116                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6117                               offset);
6118                       continue;
6119                     }
6120                   else if (bytelit == 0)
6121                     {
6122                       aopPut (AOP (result), zero, offset);
6123                       continue;
6124                     }
6125                   D (emitcode (";", "better literal AND."););
6126                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6127                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6128                                                     FALSE, FALSE, FALSE));
6129
6130                 }
6131               else
6132                 {
6133                   // faster than result <- left, anl result,right
6134                   // and better if result is SFR
6135                   if (AOP_TYPE (left) == AOP_ACC)
6136                     {
6137                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6138                                                        FALSE, FALSE, FALSE));
6139                     }
6140                   else
6141                     {
6142                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6143                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6144                       {
6145                           emitcode("mov", "b,a");
6146                           rOp = "b";
6147                       }
6148                         
6149                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6150                       emitcode ("anl", "a,%s", rOp);
6151                     }                   
6152                 }
6153               aopPut (AOP (result), "a", offset);
6154             }
6155         }
6156     }
6157
6158 release:
6159   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6160   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6161   freeAsmop (result, NULL, ic, TRUE);
6162 }
6163
6164
6165 /*-----------------------------------------------------------------*/
6166 /* genOr  - code for or                                            */
6167 /*-----------------------------------------------------------------*/
6168 static void
6169 genOr (iCode * ic, iCode * ifx)
6170 {
6171   operand *left, *right, *result;
6172   int size, offset = 0;
6173   unsigned long lit = 0L;
6174   bool     pushResult;
6175
6176   D (emitcode (";", "genOr "););
6177
6178   AOP_OP_3_NOFATAL (ic, pushResult);
6179   AOP_SET_LOCALS (ic);
6180
6181   if (pushResult)
6182   {
6183       genFarFarLogicOp(ic, "orl");
6184       return;
6185   }
6186
6187
6188 #ifdef DEBUG_TYPE
6189   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6190             AOP_TYPE (result),
6191             AOP_TYPE (left), AOP_TYPE (right));
6192   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6193             AOP_SIZE (result),
6194             AOP_SIZE (left), AOP_SIZE (right));
6195 #endif
6196
6197   /* if left is a literal & right is not then exchange them */
6198   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6199 #ifdef LOGIC_OPS_BROKEN
6200    || AOP_NEEDSACC (left) // I think this is a net loss now.
6201 #endif      
6202       )
6203     {
6204       operand *tmp = right;
6205       right = left;
6206       left = tmp;
6207     }
6208
6209   /* if result = right then exchange them */
6210   if (sameRegs (AOP (result), AOP (right)))
6211     {
6212       operand *tmp = right;
6213       right = left;
6214       left = tmp;
6215     }
6216
6217   /* if right is bit then exchange them */
6218   if (AOP_TYPE (right) == AOP_CRY &&
6219       AOP_TYPE (left) != AOP_CRY)
6220     {
6221       operand *tmp = right;
6222       right = left;
6223       left = tmp;
6224     }
6225   if (AOP_TYPE (right) == AOP_LIT)
6226     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6227
6228   size = AOP_SIZE (result);
6229
6230   // if(bit | yy)
6231   // xx = bit | yy;
6232   if (AOP_TYPE (left) == AOP_CRY)
6233     {
6234       if (AOP_TYPE (right) == AOP_LIT)
6235         {
6236           // c = bit & literal;
6237           if (lit)
6238             {
6239               // lit != 0 => result = 1
6240               if (AOP_TYPE (result) == AOP_CRY)
6241                 {
6242                   if (size)
6243                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6244                   else if (ifx)
6245                     continueIfTrue (ifx);
6246                   goto release;
6247                 }
6248               emitcode ("setb", "c");
6249             }
6250           else
6251             {
6252               // lit == 0 => result = left
6253               if (size && sameRegs (AOP (result), AOP (left)))
6254                 goto release;
6255               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6256             }
6257         }
6258       else
6259         {
6260           if (AOP_TYPE (right) == AOP_CRY)
6261             {
6262               // c = bit | bit;
6263               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6264               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6265             }
6266           else
6267             {
6268               // c = bit | val;
6269               symbol *tlbl = newiTempLabel (NULL);
6270               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6271                 emitcode ("setb", "c");
6272               emitcode ("jb", "%s,!tlabel",
6273                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6274               toBoolean (right);
6275               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6276               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6277                 {
6278                   jmpTrueOrFalse (ifx, tlbl);
6279                   goto release;
6280                 }
6281               else
6282                 {
6283                   CLRC;
6284                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6285                 }
6286             }
6287         }
6288       // bit = c
6289       // val = c
6290       if (size)
6291         outBitC (result);
6292       // if(bit | ...)
6293       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6294         genIfxJump (ifx, "c");
6295       goto release;
6296     }
6297
6298   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6299   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6300   if ((AOP_TYPE (right) == AOP_LIT) &&
6301       (AOP_TYPE (result) == AOP_CRY) &&
6302       (AOP_TYPE (left) != AOP_CRY))
6303     {
6304       if (lit)
6305         {
6306           // result = 1
6307           if (size)
6308             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6309           else
6310             continueIfTrue (ifx);
6311           goto release;
6312         }
6313       else
6314         {
6315           // lit = 0, result = boolean(left)
6316           if (size)
6317             emitcode ("setb", "c");
6318           toBoolean (right);
6319           if (size)
6320             {
6321               symbol *tlbl = newiTempLabel (NULL);
6322               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6323               CLRC;
6324               emitcode ("", "!tlabeldef", tlbl->key + 100);
6325             }
6326           else
6327             {
6328               genIfxJump (ifx, "a");
6329               goto release;
6330             }
6331         }
6332       outBitC (result);
6333       goto release;
6334     }
6335
6336   /* if left is same as result */
6337   if (sameRegs (AOP (result), AOP (left)))
6338     {
6339       for (; size--; offset++)
6340         {
6341           if (AOP_TYPE (right) == AOP_LIT)
6342             {
6343               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6344                 {
6345                   continue;
6346                 }
6347               else
6348                 {
6349                   if (IS_AOP_PREG (left))
6350                     {
6351                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6352                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6353                       aopPut (AOP (result), "a", offset);
6354                     }
6355                   else
6356                     {
6357                       emitcode ("orl", "%s,%s",
6358                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6359                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6360                     }
6361                 }
6362             }
6363           else
6364             {
6365               if (AOP_TYPE (left) == AOP_ACC)
6366                 {
6367                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6368                 }
6369               else
6370                 {
6371                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6372                   if (IS_AOP_PREG (left))
6373                     {
6374                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6375                       aopPut (AOP (result), "a", offset);
6376                     }
6377                   else
6378                     {
6379                       emitcode ("orl", "%s,a",
6380                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6381                     }
6382                 }
6383             }
6384         }
6385     }
6386   else
6387     {
6388       // left & result in different registers
6389       if (AOP_TYPE (result) == AOP_CRY)
6390         {
6391           // result = bit
6392           // if(size), result in bit
6393           // if(!size && ifx), conditional oper: if(left | right)
6394           symbol *tlbl = newiTempLabel (NULL);
6395           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6396           if (size)
6397             emitcode ("setb", "c");
6398           while (sizer--)
6399             {
6400               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6401                 emitcode ("orl", "a,%s",
6402                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6403               } else {
6404                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6405                 emitcode ("orl", "a,%s",
6406                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6407               }
6408               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6409               offset++;
6410             }
6411           if (size)
6412             {
6413               CLRC;
6414               emitcode ("", "!tlabeldef", tlbl->key + 100);
6415               outBitC (result);
6416             }
6417           else if (ifx)
6418             jmpTrueOrFalse (ifx, tlbl);
6419         }
6420       else
6421         {
6422             _startLazyDPSEvaluation();
6423           for (; (size--); offset++)
6424             {
6425               // normal case
6426               // result = left & right
6427               if (AOP_TYPE (right) == AOP_LIT)
6428                 {
6429                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6430                     {
6431                       aopPut (AOP (result),
6432                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6433                               offset);
6434                       continue;
6435                     }
6436                   D (emitcode (";", "better literal OR."););
6437                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6438                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6439                                                     FALSE, FALSE, FALSE));
6440
6441                 }
6442               else
6443                 {
6444                   // faster than result <- left, anl result,right
6445                   // and better if result is SFR
6446                   if (AOP_TYPE (left) == AOP_ACC)
6447                     {
6448                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6449                                                        FALSE, FALSE, FALSE));
6450                     }
6451                   else
6452                     {
6453                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6454                         
6455                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6456                       {
6457                           emitcode("mov", "b,a");
6458                           rOp = "b";
6459                       }
6460                         
6461                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6462                       emitcode ("orl", "a,%s", rOp);
6463                     }
6464                 }
6465               aopPut (AOP (result), "a", offset);
6466             }
6467             _endLazyDPSEvaluation();
6468         }
6469     }
6470
6471 release:
6472   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6473   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6474   freeAsmop (result, NULL, ic, TRUE);
6475 }
6476
6477 /*-----------------------------------------------------------------*/
6478 /* genXor - code for xclusive or                                   */
6479 /*-----------------------------------------------------------------*/
6480 static void
6481 genXor (iCode * ic, iCode * ifx)
6482 {
6483   operand *left, *right, *result;
6484   int size, offset = 0;
6485   unsigned long lit = 0L;
6486   bool pushResult;
6487
6488   D (emitcode (";", "genXor "););
6489
6490   AOP_OP_3_NOFATAL (ic, pushResult);
6491   AOP_SET_LOCALS (ic);
6492
6493   if (pushResult)
6494   {
6495       genFarFarLogicOp(ic, "xrl");
6496       return;
6497   }  
6498
6499 #ifdef DEBUG_TYPE
6500   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6501             AOP_TYPE (result),
6502             AOP_TYPE (left), AOP_TYPE (right));
6503   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6504             AOP_SIZE (result),
6505             AOP_SIZE (left), AOP_SIZE (right));
6506 #endif
6507
6508   /* if left is a literal & right is not ||
6509      if left needs acc & right does not */
6510   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6511 #ifdef LOGIC_OPS_BROKEN      
6512       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6513 #endif
6514      )
6515     {
6516       operand *tmp = right;
6517       right = left;
6518       left = tmp;
6519     }
6520
6521   /* if result = right then exchange them */
6522   if (sameRegs (AOP (result), AOP (right)))
6523     {
6524       operand *tmp = right;
6525       right = left;
6526       left = tmp;
6527     }
6528
6529   /* if right is bit then exchange them */
6530   if (AOP_TYPE (right) == AOP_CRY &&
6531       AOP_TYPE (left) != AOP_CRY)
6532     {
6533       operand *tmp = right;
6534       right = left;
6535       left = tmp;
6536     }
6537   if (AOP_TYPE (right) == AOP_LIT)
6538     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6539
6540   size = AOP_SIZE (result);
6541
6542   // if(bit ^ yy)
6543   // xx = bit ^ yy;
6544   if (AOP_TYPE (left) == AOP_CRY)
6545     {
6546       if (AOP_TYPE (right) == AOP_LIT)
6547         {
6548           // c = bit & literal;
6549           if (lit >> 1)
6550             {
6551               // lit>>1  != 0 => result = 1
6552               if (AOP_TYPE (result) == AOP_CRY)
6553                 {
6554                   if (size)
6555                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6556                   else if (ifx)
6557                     continueIfTrue (ifx);
6558                   goto release;
6559                 }
6560               emitcode ("setb", "c");
6561             }
6562           else
6563             {
6564               // lit == (0 or 1)
6565               if (lit == 0)
6566                 {
6567                   // lit == 0, result = left
6568                   if (size && sameRegs (AOP (result), AOP (left)))
6569                     goto release;
6570                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6571                 }
6572               else
6573                 {
6574                   // lit == 1, result = not(left)
6575                   if (size && sameRegs (AOP (result), AOP (left)))
6576                     {
6577                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6578                       goto release;
6579                     }
6580                   else
6581                     {
6582                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6583                       emitcode ("cpl", "c");
6584                     }
6585                 }
6586             }
6587
6588         }
6589       else
6590         {
6591           // right != literal
6592           symbol *tlbl = newiTempLabel (NULL);
6593           if (AOP_TYPE (right) == AOP_CRY)
6594             {
6595               // c = bit ^ bit;
6596               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6597             }
6598           else
6599             {
6600               int sizer = AOP_SIZE (right);
6601               // c = bit ^ val
6602               // if val>>1 != 0, result = 1
6603               emitcode ("setb", "c");
6604               while (sizer)
6605                 {
6606                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6607                   if (sizer == 1)
6608                     // test the msb of the lsb
6609                     emitcode ("anl", "a,#!constbyte",0xfe);
6610                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6611                   sizer--;
6612                 }
6613               // val = (0,1)
6614               emitcode ("rrc", "a");
6615             }
6616           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6617           emitcode ("cpl", "c");
6618           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6619         }
6620       // bit = c
6621       // val = c
6622       if (size)
6623         outBitC (result);
6624       // if(bit | ...)
6625       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6626         genIfxJump (ifx, "c");
6627       goto release;
6628     }
6629
6630   if (sameRegs (AOP (result), AOP (left)))
6631     {
6632       /* if left is same as result */
6633       for (; size--; offset++)
6634         {
6635           if (AOP_TYPE (right) == AOP_LIT)
6636             {
6637               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6638                 continue;
6639               else if (IS_AOP_PREG (left))
6640                 {
6641                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6642                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6643                   aopPut (AOP (result), "a", offset);
6644                 }
6645               else
6646                 emitcode ("xrl", "%s,%s",
6647                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6648                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6649             }
6650           else
6651             {
6652               if (AOP_TYPE (left) == AOP_ACC)
6653                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6654               else
6655                 {
6656                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6657                   if (IS_AOP_PREG (left))
6658                     {
6659                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6660                       aopPut (AOP (result), "a", offset);
6661                     }
6662                   else
6663                     emitcode ("xrl", "%s,a",
6664                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6665                 }
6666             }
6667         }
6668     }
6669   else
6670     {
6671       // left & result in different registers
6672       if (AOP_TYPE (result) == AOP_CRY)
6673         {
6674           // result = bit
6675           // if(size), result in bit
6676           // if(!size && ifx), conditional oper: if(left ^ right)
6677           symbol *tlbl = newiTempLabel (NULL);
6678           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6679                   
6680           if (size)
6681             emitcode ("setb", "c");
6682           while (sizer--)
6683             {
6684               if ((AOP_TYPE (right) == AOP_LIT) &&
6685                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6686                 {
6687                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6688                 }
6689               else
6690                 {
6691                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6692                     emitcode ("xrl", "a,%s",
6693                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6694                   } else {
6695                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6696                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6697                       {
6698                           emitcode("mov", "b,a");
6699                           rOp = "b";
6700                       }
6701                         
6702                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6703                       emitcode ("xrl", "a,%s", rOp);                  
6704                   }
6705                 }
6706               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6707               offset++;
6708             }
6709           if (size)
6710             {
6711               CLRC;
6712               emitcode ("", "!tlabeldef", tlbl->key + 100);
6713               outBitC (result);
6714             }
6715           else if (ifx)
6716             jmpTrueOrFalse (ifx, tlbl);
6717         }
6718       else
6719         {
6720         for (; (size--); offset++)
6721           {
6722             // normal case
6723             // result = left & right
6724             if (AOP_TYPE (right) == AOP_LIT)
6725               {
6726                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6727                   {
6728                     aopPut (AOP (result),
6729                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6730                             offset);
6731                     continue;
6732                   }
6733                 D (emitcode (";", "better literal XOR."););
6734                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6735                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6736                                                   FALSE, FALSE, FALSE));
6737               }
6738             else
6739               {
6740                 // faster than result <- left, anl result,right
6741                 // and better if result is SFR
6742                 if (AOP_TYPE (left) == AOP_ACC)
6743                   {
6744                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6745                                                      FALSE, FALSE, FALSE));
6746                   }
6747                 else
6748                   {
6749                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6750                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6751                       {
6752                           emitcode("mov", "b,a");
6753                           rOp = "b";
6754                       }
6755                         
6756                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6757                       emitcode ("xrl", "a,%s", rOp);
6758                   }
6759               }
6760             aopPut (AOP (result), "a", offset);
6761           }
6762         }
6763         
6764     }
6765
6766 release:
6767   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6768   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6769   freeAsmop (result, NULL, ic, TRUE);
6770 }
6771
6772 /*-----------------------------------------------------------------*/
6773 /* genInline - write the inline code out                           */
6774 /*-----------------------------------------------------------------*/
6775 static void
6776 genInline (iCode * ic)
6777 {
6778   char *buffer, *bp, *bp1;
6779
6780   D (emitcode (";", "genInline ");
6781     );
6782
6783   _G.inLine += (!options.asmpeep);
6784
6785   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6786   strcpy (buffer, IC_INLINE (ic));
6787
6788   /* emit each line as a code */
6789   while (*bp)
6790     {
6791       if (*bp == '\n')
6792         {
6793           *bp++ = '\0';
6794           emitcode (bp1, "");
6795           bp1 = bp;
6796         }
6797       else
6798         {
6799           if (*bp == ':')
6800             {
6801               bp++;
6802               *bp = '\0';
6803               bp++;
6804               emitcode (bp1, "");
6805               bp1 = bp;
6806             }
6807           else
6808             bp++;
6809         }
6810     }
6811   if (bp1 != bp)
6812     emitcode (bp1, "");
6813   /*     emitcode("",buffer); */
6814   _G.inLine -= (!options.asmpeep);
6815 }
6816
6817 /*-----------------------------------------------------------------*/
6818 /* genRRC - rotate right with carry                                */
6819 /*-----------------------------------------------------------------*/
6820 static void
6821 genRRC (iCode * ic)
6822 {
6823   operand *left, *result;
6824   int size, offset = 0;
6825   char *l;
6826
6827   D (emitcode (";", "genRRC ");
6828     );
6829
6830   /* rotate right with carry */
6831   left = IC_LEFT (ic);
6832   result = IC_RESULT (ic);
6833   aopOp (left, ic, FALSE, FALSE);
6834   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6835
6836   /* move it to the result */
6837   size = AOP_SIZE (result);
6838   offset = size - 1;
6839   CLRC;
6840
6841   _startLazyDPSEvaluation ();
6842   while (size--)
6843     {
6844       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6845       MOVA (l);
6846       emitcode ("rrc", "a");
6847       if (AOP_SIZE (result) > 1)
6848         aopPut (AOP (result), "a", offset--);
6849     }
6850   _endLazyDPSEvaluation ();
6851
6852   /* now we need to put the carry into the
6853      highest order byte of the result */
6854   if (AOP_SIZE (result) > 1)
6855     {
6856       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6857       MOVA (l);
6858     }
6859   emitcode ("mov", "acc.7,c");
6860   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6861   freeAsmop (left, NULL, ic, TRUE);
6862   freeAsmop (result, NULL, ic, TRUE);
6863 }
6864
6865 /*-----------------------------------------------------------------*/
6866 /* genRLC - generate code for rotate left with carry               */
6867 /*-----------------------------------------------------------------*/
6868 static void
6869 genRLC (iCode * ic)
6870 {
6871   operand *left, *result;
6872   int size, offset = 0;
6873   char *l;
6874
6875   D (emitcode (";", "genRLC ");
6876     );
6877
6878   /* rotate right with carry */
6879   left = IC_LEFT (ic);
6880   result = IC_RESULT (ic);
6881   aopOp (left, ic, FALSE, FALSE);
6882   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6883
6884   /* move it to the result */
6885   size = AOP_SIZE (result);
6886   offset = 0;
6887   if (size--)
6888     {
6889       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6890       MOVA (l);
6891       emitcode ("add", "a,acc");
6892       if (AOP_SIZE (result) > 1)
6893         {
6894           aopPut (AOP (result), "a", offset++);
6895         }
6896
6897       _startLazyDPSEvaluation ();
6898       while (size--)
6899         {
6900           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6901           MOVA (l);
6902           emitcode ("rlc", "a");
6903           if (AOP_SIZE (result) > 1)
6904             aopPut (AOP (result), "a", offset++);
6905         }
6906       _endLazyDPSEvaluation ();
6907     }
6908   /* now we need to put the carry into the
6909      highest order byte of the result */
6910   if (AOP_SIZE (result) > 1)
6911     {
6912       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6913       MOVA (l);
6914     }
6915   emitcode ("mov", "acc.0,c");
6916   aopPut (AOP (result), "a", 0);
6917   freeAsmop (left, NULL, ic, TRUE);
6918   freeAsmop (result, NULL, ic, TRUE);
6919 }
6920
6921 /*-----------------------------------------------------------------*/
6922 /* genGetHbit - generates code get highest order bit               */
6923 /*-----------------------------------------------------------------*/
6924 static void
6925 genGetHbit (iCode * ic)
6926 {
6927   operand *left, *result;
6928   left = IC_LEFT (ic);
6929   result = IC_RESULT (ic);
6930   aopOp (left, ic, FALSE, FALSE);
6931   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6932
6933   D (emitcode (";", "genGetHbit ");
6934     );
6935
6936   /* get the highest order byte into a */
6937   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6938   if (AOP_TYPE (result) == AOP_CRY)
6939     {
6940       emitcode ("rlc", "a");
6941       outBitC (result);
6942     }
6943   else
6944     {
6945       emitcode ("rl", "a");
6946       emitcode ("anl", "a,#1");
6947       outAcc (result);
6948     }
6949
6950
6951   freeAsmop (left, NULL, ic, TRUE);
6952   freeAsmop (result, NULL, ic, TRUE);
6953 }
6954
6955 /*-----------------------------------------------------------------*/
6956 /* AccRol - rotate left accumulator by known count                 */
6957 /*-----------------------------------------------------------------*/
6958 static void
6959 AccRol (int shCount)
6960 {
6961   shCount &= 0x0007;            // shCount : 0..7
6962
6963   switch (shCount)
6964     {
6965     case 0:
6966       break;
6967     case 1:
6968       emitcode ("rl", "a");
6969       break;
6970     case 2:
6971       emitcode ("rl", "a");
6972       emitcode ("rl", "a");
6973       break;
6974     case 3:
6975       emitcode ("swap", "a");
6976       emitcode ("rr", "a");
6977       break;
6978     case 4:
6979       emitcode ("swap", "a");
6980       break;
6981     case 5:
6982       emitcode ("swap", "a");
6983       emitcode ("rl", "a");
6984       break;
6985     case 6:
6986       emitcode ("rr", "a");
6987       emitcode ("rr", "a");
6988       break;
6989     case 7:
6990       emitcode ("rr", "a");
6991       break;
6992     }
6993 }
6994
6995 /*-----------------------------------------------------------------*/
6996 /* AccLsh - left shift accumulator by known count                  */
6997 /*-----------------------------------------------------------------*/
6998 static void
6999 AccLsh (int shCount)
7000 {
7001   if (shCount != 0)
7002     {
7003       if (shCount == 1)
7004         emitcode ("add", "a,acc");
7005       else if (shCount == 2)
7006         {
7007           emitcode ("add", "a,acc");
7008           emitcode ("add", "a,acc");
7009         }
7010       else
7011         {
7012           /* rotate left accumulator */
7013           AccRol (shCount);
7014           /* and kill the lower order bits */
7015           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7016         }
7017     }
7018 }
7019
7020 /*-----------------------------------------------------------------*/
7021 /* AccRsh - right shift accumulator by known count                 */
7022 /*-----------------------------------------------------------------*/
7023 static void
7024 AccRsh (int shCount)
7025 {
7026   if (shCount != 0)
7027     {
7028       if (shCount == 1)
7029         {
7030           CLRC;
7031           emitcode ("rrc", "a");
7032         }
7033       else
7034         {
7035           /* rotate right accumulator */
7036           AccRol (8 - shCount);
7037           /* and kill the higher order bits */
7038           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7039         }
7040     }
7041 }
7042
7043 #ifdef BETTER_LITERAL_SHIFT
7044 /*-----------------------------------------------------------------*/
7045 /* AccSRsh - signed right shift accumulator by known count                 */
7046 /*-----------------------------------------------------------------*/
7047 static void
7048 AccSRsh (int shCount)
7049 {
7050   symbol *tlbl;
7051   if (shCount != 0)
7052     {
7053       if (shCount == 1)
7054         {
7055           emitcode ("mov", "c,acc.7");
7056           emitcode ("rrc", "a");
7057         }
7058       else if (shCount == 2)
7059         {
7060           emitcode ("mov", "c,acc.7");
7061           emitcode ("rrc", "a");
7062           emitcode ("mov", "c,acc.7");
7063           emitcode ("rrc", "a");
7064         }
7065       else
7066         {
7067           tlbl = newiTempLabel (NULL);
7068           /* rotate right accumulator */
7069           AccRol (8 - shCount);
7070           /* and kill the higher order bits */
7071           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7072           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7073           emitcode ("orl", "a,#!constbyte",
7074                     (unsigned char) ~SRMask[shCount]);
7075           emitcode ("", "!tlabeldef", tlbl->key + 100);
7076         }
7077     }
7078 }
7079 #endif
7080
7081 #ifdef BETTER_LITERAL_SHIFT
7082 /*-----------------------------------------------------------------*/
7083 /* shiftR1Left2Result - shift right one byte from left to result   */
7084 /*-----------------------------------------------------------------*/
7085 static void
7086 shiftR1Left2Result (operand * left, int offl,
7087                     operand * result, int offr,
7088                     int shCount, int sign)
7089 {
7090   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7091   /* shift right accumulator */
7092   if (sign)
7093     AccSRsh (shCount);
7094   else
7095     AccRsh (shCount);
7096   aopPut (AOP (result), "a", offr);
7097 }
7098 #endif
7099
7100 #ifdef BETTER_LITERAL_SHIFT
7101 /*-----------------------------------------------------------------*/
7102 /* shiftL1Left2Result - shift left one byte from left to result    */
7103 /*-----------------------------------------------------------------*/
7104 static void
7105 shiftL1Left2Result (operand * left, int offl,
7106                     operand * result, int offr, int shCount)
7107 {
7108   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7109   /* shift left accumulator */
7110   AccLsh (shCount);
7111   aopPut (AOP (result), "a", offr);
7112 }
7113 #endif
7114
7115 #ifdef BETTER_LITERAL_SHIFT
7116 /*-----------------------------------------------------------------*/
7117 /* movLeft2Result - move byte from left to result                  */
7118 /*-----------------------------------------------------------------*/
7119 static void
7120 movLeft2Result (operand * left, int offl,
7121                 operand * result, int offr, int sign)
7122 {
7123   char *l;
7124   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7125   {
7126       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7127
7128       if (*l == '@' && (IS_AOP_PREG (result)))
7129       {
7130           emitcode ("mov", "a,%s", l);
7131           aopPut (AOP (result), "a", offr);
7132       }
7133       else
7134       {
7135           if (!sign)
7136           {
7137             aopPut (AOP (result), l, offr);
7138           }
7139           else
7140             {
7141               /* MSB sign in acc.7 ! */
7142               if (getDataSize (left) == offl + 1)
7143                 {
7144                   emitcode ("mov", "a,%s", l);
7145                   aopPut (AOP (result), "a", offr);
7146                 }
7147             }
7148       }
7149   }
7150 }
7151 #endif
7152
7153 #ifdef BETTER_LITERAL_SHIFT
7154 /*-----------------------------------------------------------------*/
7155 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7156 /*-----------------------------------------------------------------*/
7157 static void
7158 AccAXRrl1 (char *x)
7159 {
7160   emitcode ("rrc", "a");
7161   emitcode ("xch", "a,%s", x);
7162   emitcode ("rrc", "a");
7163   emitcode ("xch", "a,%s", x);
7164 }
7165 #endif
7166
7167 #ifdef BETTER_LITERAL_SHIFT
7168 //REMOVE ME!!!
7169 /*-----------------------------------------------------------------*/
7170 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7171 /*-----------------------------------------------------------------*/
7172 static void
7173 AccAXLrl1 (char *x)
7174 {
7175   emitcode ("xch", "a,%s", x);
7176   emitcode ("rlc", "a");
7177   emitcode ("xch", "a,%s", x);
7178   emitcode ("rlc", "a");
7179 }
7180 #endif
7181
7182 #ifdef BETTER_LITERAL_SHIFT
7183 /*-----------------------------------------------------------------*/
7184 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7185 /*-----------------------------------------------------------------*/
7186 static void
7187 AccAXLsh1 (char *x)
7188 {
7189   emitcode ("xch", "a,%s", x);
7190   emitcode ("add", "a,acc");
7191   emitcode ("xch", "a,%s", x);
7192   emitcode ("rlc", "a");
7193 }
7194 #endif
7195
7196 #ifdef BETTER_LITERAL_SHIFT
7197 /*-----------------------------------------------------------------*/
7198 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7199 /*-----------------------------------------------------------------*/
7200 static void
7201 AccAXLsh (char *x, int shCount)
7202 {
7203   switch (shCount)
7204     {
7205     case 0:
7206       break;
7207     case 1:
7208       AccAXLsh1 (x);
7209       break;
7210     case 2:
7211       AccAXLsh1 (x);
7212       AccAXLsh1 (x);
7213       break;
7214     case 3:
7215     case 4:
7216     case 5:                     // AAAAABBB:CCCCCDDD
7217
7218       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7219
7220       emitcode ("anl", "a,#!constbyte",
7221                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7222
7223       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7224
7225       AccRol (shCount);         // DDDCCCCC:BBB00000
7226
7227       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7228
7229       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7230
7231       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7232
7233       emitcode ("anl", "a,#!constbyte",
7234                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7235
7236       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7237
7238       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7239
7240       break;
7241     case 6:                     // AAAAAABB:CCCCCCDD
7242       emitcode ("anl", "a,#!constbyte",
7243                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7244       emitcode ("mov", "c,acc.0");      // c = B
7245       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7246 #if 0
7247       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7248       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7249 #else
7250       emitcode("rrc","a"); 
7251       emitcode("xch","a,%s", x); 
7252       emitcode("rrc","a"); 
7253       emitcode("mov","c,acc.0"); //<< get correct bit 
7254       emitcode("xch","a,%s", x); 
7255
7256       emitcode("rrc","a"); 
7257       emitcode("xch","a,%s", x); 
7258       emitcode("rrc","a"); 
7259       emitcode("xch","a,%s", x); 
7260 #endif
7261       break;
7262     case 7:                     // a:x <<= 7
7263
7264       emitcode ("anl", "a,#!constbyte",
7265                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7266
7267       emitcode ("mov", "c,acc.0");      // c = B
7268
7269       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7270
7271       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7272
7273       break;
7274     default:
7275       break;
7276     }
7277 }
7278 #endif
7279
7280 #ifdef BETTER_LITERAL_SHIFT
7281 //REMOVE ME!!!
7282 /*-----------------------------------------------------------------*/
7283 /* AccAXRsh - right shift a:x known count (0..7)                   */
7284 /*-----------------------------------------------------------------*/
7285 static void
7286 AccAXRsh (char *x, int shCount)
7287 {
7288   switch (shCount)
7289     {
7290     case 0:
7291       break;
7292     case 1:
7293       CLRC;
7294       AccAXRrl1 (x);            // 0->a:x
7295
7296       break;
7297     case 2:
7298       CLRC;
7299       AccAXRrl1 (x);            // 0->a:x
7300
7301       CLRC;
7302       AccAXRrl1 (x);            // 0->a:x
7303
7304       break;
7305     case 3:
7306     case 4:
7307     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7308
7309       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7310
7311       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7312
7313       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7314
7315       emitcode ("anl", "a,#!constbyte",
7316                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7317
7318       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7319
7320       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7321
7322       emitcode ("anl", "a,#!constbyte",
7323                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7324
7325       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7326
7327       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7328
7329       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7330
7331       break;
7332     case 6:                     // AABBBBBB:CCDDDDDD
7333
7334       emitcode ("mov", "c,acc.7");
7335       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7336
7337       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7338
7339       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7340
7341       emitcode ("anl", "a,#!constbyte",
7342                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7343
7344       break;
7345     case 7:                     // ABBBBBBB:CDDDDDDD
7346
7347       emitcode ("mov", "c,acc.7");      // c = A
7348
7349       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7350
7351       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7352
7353       emitcode ("anl", "a,#!constbyte",
7354                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7355
7356       break;
7357     default:
7358       break;
7359     }
7360 }
7361 #endif
7362
7363 #ifdef BETTER_LITERAL_SHIFT
7364 /*-----------------------------------------------------------------*/
7365 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7366 /*-----------------------------------------------------------------*/
7367 static void
7368 AccAXRshS (char *x, int shCount)
7369 {
7370   symbol *tlbl;
7371   switch (shCount)
7372     {
7373     case 0:
7374       break;
7375     case 1:
7376       emitcode ("mov", "c,acc.7");
7377       AccAXRrl1 (x);            // s->a:x
7378
7379       break;
7380     case 2:
7381       emitcode ("mov", "c,acc.7");
7382       AccAXRrl1 (x);            // s->a:x
7383
7384       emitcode ("mov", "c,acc.7");
7385       AccAXRrl1 (x);            // s->a:x
7386
7387       break;
7388     case 3:
7389     case 4:
7390     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7391
7392       tlbl = newiTempLabel (NULL);
7393       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7394
7395       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7396
7397       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7398
7399       emitcode ("anl", "a,#!constbyte",
7400                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7401
7402       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7403
7404       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7405
7406       emitcode ("anl", "a,#!constbyte",
7407                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7408
7409       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7410
7411       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7412
7413       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7414
7415       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7416       emitcode ("orl", "a,#!constbyte",
7417                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7418
7419       emitcode ("", "!tlabeldef", tlbl->key + 100);
7420       break;                    // SSSSAAAA:BBBCCCCC
7421
7422     case 6:                     // AABBBBBB:CCDDDDDD
7423
7424       tlbl = newiTempLabel (NULL);
7425       emitcode ("mov", "c,acc.7");
7426       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7427
7428       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7429
7430       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7431
7432       emitcode ("anl", "a,#!constbyte",
7433                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7434
7435       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7436       emitcode ("orl", "a,#!constbyte",
7437                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7438
7439       emitcode ("", "!tlabeldef", tlbl->key + 100);
7440       break;
7441     case 7:                     // ABBBBBBB:CDDDDDDD
7442
7443       tlbl = newiTempLabel (NULL);
7444       emitcode ("mov", "c,acc.7");      // c = A
7445
7446       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7447
7448       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7449
7450       emitcode ("anl", "a,#!constbyte",
7451                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7452
7453       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7454       emitcode ("orl", "a,#!constbyte",
7455                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7456
7457       emitcode ("", "!tlabeldef", tlbl->key + 100);
7458       break;
7459     default:
7460       break;
7461     }
7462 }
7463 #endif
7464
7465 #ifdef BETTER_LITERAL_SHIFT
7466 static void
7467 _loadLeftIntoAx(char    **lsb, 
7468                 operand *left, 
7469                 operand *result,
7470                 int     offl,
7471                 int     offr)
7472 {
7473   // Get the initial value from left into a pair of registers.
7474   // MSB must be in A, LSB can be any register.
7475   //
7476   // If the result is held in registers, it is an optimization
7477   // if the LSB can be held in the register which will hold the,
7478   // result LSB since this saves us from having to copy it into
7479   // the result following AccAXLsh.
7480   //
7481   // If the result is addressed indirectly, this is not a gain.
7482   if (AOP_NEEDSACC(result))
7483   {
7484        char *leftByte;
7485        
7486        _startLazyDPSEvaluation();
7487       if (AOP_TYPE(left) == AOP_DPTR2)
7488        {
7489            // Get MSB in A.
7490            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7491            // get LSB in DP2_RESULT_REG.
7492            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7493            assert(!strcmp(leftByte, DP2_RESULT_REG));
7494        }
7495        else
7496        {
7497            // get LSB into DP2_RESULT_REG
7498            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7499            if (strcmp(leftByte, DP2_RESULT_REG))
7500            {
7501                TR_AP("#7");
7502                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7503            }
7504            // And MSB in A.
7505            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7506            assert(strcmp(leftByte, DP2_RESULT_REG));
7507            MOVA(leftByte);
7508        }
7509        _endLazyDPSEvaluation();
7510        *lsb = DP2_RESULT_REG;
7511   }
7512   else
7513   {
7514       if (sameRegs (AOP (result), AOP (left)) &&
7515         ((offl + MSB16) == offr))
7516       {
7517           /* don't crash result[offr] */
7518           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7519           emitcode ("xch", "a,%s", 
7520                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7521       }
7522       else
7523       {
7524           movLeft2Result (left, offl, result, offr, 0);
7525           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7526       }
7527       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7528       assert(strcmp(*lsb,"a"));      
7529   }
7530 }
7531
7532 static void
7533 _storeAxResults(char    *lsb,
7534                 operand *result,
7535                 int     offr)
7536 {
7537   _startLazyDPSEvaluation();
7538   if (AOP_NEEDSACC(result))
7539   {
7540       /* We have to explicitly update the result LSB.
7541        */
7542       emitcode("xch","a,%s", lsb);
7543       aopPut(AOP(result), "a", offr);
7544       emitcode("mov","a,%s", lsb);
7545   }
7546   if (getDataSize (result) > 1)
7547   {
7548       aopPut (AOP (result), "a", offr + MSB16);
7549   }
7550   _endLazyDPSEvaluation();
7551 }
7552
7553 /*-----------------------------------------------------------------*/
7554 /* shiftL2Left2Result - shift left two bytes from left to result   */
7555 /*-----------------------------------------------------------------*/
7556 static void
7557 shiftL2Left2Result (operand * left, int offl,
7558                     operand * result, int offr, int shCount)
7559 {
7560   char *lsb;
7561
7562   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7563   
7564   AccAXLsh (lsb, shCount);
7565   
7566   _storeAxResults(lsb, result, offr);
7567 }
7568 #endif
7569
7570 #ifdef BETTER_LITERAL_SHIFT
7571 /*-----------------------------------------------------------------*/
7572 /* shiftR2Left2Result - shift right two bytes from left to result  */
7573 /*-----------------------------------------------------------------*/
7574 static void
7575 shiftR2Left2Result (operand * left, int offl,
7576                     operand * result, int offr,
7577                     int shCount, int sign)
7578 {
7579   char *lsb;
7580   
7581   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7582   
7583   /* a:x >> shCount (x = lsb(result)) */
7584   if (sign)
7585   {
7586      AccAXRshS(lsb, shCount);
7587   }
7588   else
7589   {
7590     AccAXRsh(lsb, shCount);
7591   }
7592   
7593   _storeAxResults(lsb, result, offr);
7594 }
7595 #endif
7596
7597 #if 0
7598 //REMOVE ME!!!
7599 /*-----------------------------------------------------------------*/
7600 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7601 /*-----------------------------------------------------------------*/
7602 static void
7603 shiftLLeftOrResult (operand * left, int offl,
7604                     operand * result, int offr, int shCount)
7605 {
7606   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7607   /* shift left accumulator */
7608   AccLsh (shCount);
7609   /* or with result */
7610   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7611   /* back to result */
7612   aopPut (AOP (result), "a", offr);
7613 }
7614 #endif
7615
7616 #if 0
7617 //REMOVE ME!!!
7618 /*-----------------------------------------------------------------*/
7619 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7620 /*-----------------------------------------------------------------*/
7621 static void
7622 shiftRLeftOrResult (operand * left, int offl,
7623                     operand * result, int offr, int shCount)
7624 {
7625   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7626   /* shift right accumulator */
7627   AccRsh (shCount);
7628   /* or with result */
7629   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7630   /* back to result */
7631   aopPut (AOP (result), "a", offr);
7632 }
7633 #endif
7634
7635 #ifdef BETTER_LITERAL_SHIFT
7636 /*-----------------------------------------------------------------*/
7637 /* genlshOne - left shift a one byte quantity by known count       */
7638 /*-----------------------------------------------------------------*/
7639 static void
7640 genlshOne (operand * result, operand * left, int shCount)
7641 {
7642   D (emitcode (";", "genlshOne "););
7643   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7644 }
7645 #endif
7646
7647 #ifdef BETTER_LITERAL_SHIFT
7648 /*-----------------------------------------------------------------*/
7649 /* genlshTwo - left shift two bytes by known amount != 0           */
7650 /*-----------------------------------------------------------------*/
7651 static void
7652 genlshTwo (operand * result, operand * left, int shCount)
7653 {
7654   int size;
7655
7656   D (emitcode (";", "genlshTwo "););
7657
7658   size = getDataSize (result);
7659
7660   /* if shCount >= 8 */
7661   if (shCount >= 8)
7662   {
7663       shCount -= 8;
7664
7665       _startLazyDPSEvaluation();
7666
7667       if (size > 1)
7668         {
7669           if (shCount)
7670           {
7671             _endLazyDPSEvaluation();
7672             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7673             aopPut (AOP (result), zero, LSB);       
7674           }
7675           else
7676           {
7677             movLeft2Result (left, LSB, result, MSB16, 0);
7678             aopPut (AOP (result), zero, LSB);
7679             _endLazyDPSEvaluation();
7680           }
7681         }
7682         else
7683         {
7684           aopPut (AOP (result), zero, LSB);
7685           _endLazyDPSEvaluation();
7686         }
7687   }
7688
7689   /*  1 <= shCount <= 7 */
7690   else
7691     {
7692       if (size == 1)
7693       {
7694         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7695       }
7696       else
7697       {
7698         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7699       }
7700     }
7701 }
7702 #endif
7703
7704 #if 0
7705 //REMOVE ME!!!
7706 /*-----------------------------------------------------------------*/
7707 /* shiftLLong - shift left one long from left to result            */
7708 /* offl = LSB or MSB16                                             */
7709 /*-----------------------------------------------------------------*/
7710 static void
7711 shiftLLong (operand * left, operand * result, int offr)
7712 {
7713   char *l;
7714   int size = AOP_SIZE (result);
7715
7716   if (size >= LSB + offr)
7717     {
7718       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7719       MOVA (l);
7720       emitcode ("add", "a,acc");
7721       if (sameRegs (AOP (left), AOP (result)) &&
7722           size >= MSB16 + offr && offr != LSB)
7723         emitcode ("xch", "a,%s",
7724                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7725       else
7726         aopPut (AOP (result), "a", LSB + offr);
7727     }
7728
7729   if (size >= MSB16 + offr)
7730     {
7731       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7732         {
7733           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7734           MOVA (l);
7735         }
7736       emitcode ("rlc", "a");
7737       if (sameRegs (AOP (left), AOP (result)) &&
7738           size >= MSB24 + offr && offr != LSB)
7739         emitcode ("xch", "a,%s",
7740                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7741       else
7742         aopPut (AOP (result), "a", MSB16 + offr);
7743     }
7744
7745   if (size >= MSB24 + offr)
7746     {
7747       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7748         {
7749           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7750           MOVA (l);
7751         }
7752       emitcode ("rlc", "a");
7753       if (sameRegs (AOP (left), AOP (result)) &&
7754           size >= MSB32 + offr && offr != LSB)
7755         emitcode ("xch", "a,%s",
7756                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7757       else
7758         aopPut (AOP (result), "a", MSB24 + offr);
7759     }
7760
7761   if (size > MSB32 + offr)
7762     {
7763       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7764         {
7765           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7766           MOVA (l);
7767         }
7768       emitcode ("rlc", "a");
7769       aopPut (AOP (result), "a", MSB32 + offr);
7770     }
7771   if (offr != LSB)
7772     aopPut (AOP (result), zero, LSB);
7773 }
7774 #endif
7775
7776 #if 0
7777 //REMOVE ME!!!
7778 /*-----------------------------------------------------------------*/
7779 /* genlshFour - shift four byte by a known amount != 0             */
7780 /*-----------------------------------------------------------------*/
7781 static void
7782 genlshFour (operand * result, operand * left, int shCount)
7783 {
7784   int size;
7785
7786   D (emitcode (";", "genlshFour ");
7787     );
7788
7789   size = AOP_SIZE (result);
7790
7791   /* if shifting more that 3 bytes */
7792   if (shCount >= 24)
7793     {
7794       shCount -= 24;
7795       if (shCount)
7796         /* lowest order of left goes to the highest
7797            order of the destination */
7798         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7799       else
7800         movLeft2Result (left, LSB, result, MSB32, 0);
7801       aopPut (AOP (result), zero, LSB);
7802       aopPut (AOP (result), zero, MSB16);
7803       aopPut (AOP (result), zero, MSB24);
7804       return;
7805     }
7806
7807   /* more than two bytes */
7808   else if (shCount >= 16)
7809     {
7810       /* lower order two bytes goes to higher order two bytes */
7811       shCount -= 16;
7812       /* if some more remaining */
7813       if (shCount)
7814         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7815       else
7816         {
7817           movLeft2Result (left, MSB16, result, MSB32, 0);
7818           movLeft2Result (left, LSB, result, MSB24, 0);
7819         }
7820       aopPut (AOP (result), zero, MSB16);
7821       aopPut (AOP (result), zero, LSB);
7822       return;
7823     }
7824
7825   /* if more than 1 byte */
7826   else if (shCount >= 8)
7827     {
7828       /* lower order three bytes goes to higher order  three bytes */
7829       shCount -= 8;
7830       if (size == 2)
7831         {
7832           if (shCount)
7833             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7834           else
7835             movLeft2Result (left, LSB, result, MSB16, 0);
7836         }
7837       else
7838         {                       /* size = 4 */
7839           if (shCount == 0)
7840             {
7841               movLeft2Result (left, MSB24, result, MSB32, 0);
7842               movLeft2Result (left, MSB16, result, MSB24, 0);
7843               movLeft2Result (left, LSB, result, MSB16, 0);
7844               aopPut (AOP (result), zero, LSB);
7845             }
7846           else if (shCount == 1)
7847             shiftLLong (left, result, MSB16);
7848           else
7849             {
7850               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7851               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7852               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7853               aopPut (AOP (result), zero, LSB);
7854             }
7855         }
7856     }
7857
7858   /* 1 <= shCount <= 7 */
7859   else if (shCount <= 2)
7860     {
7861       shiftLLong (left, result, LSB);
7862       if (shCount == 2)
7863         shiftLLong (result, result, LSB);
7864     }
7865   /* 3 <= shCount <= 7, optimize */
7866   else
7867     {
7868       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7869       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7870       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7871     }
7872 }
7873 #endif
7874
7875 #ifdef BETTER_LITERAL_SHIFT
7876 /*-----------------------------------------------------------------*/
7877 /* genLeftShiftLiteral - left shifting by known count              */
7878 /*-----------------------------------------------------------------*/
7879 static bool
7880 genLeftShiftLiteral (operand * left,
7881                      operand * right,
7882                      operand * result,
7883                      iCode * ic)
7884 {
7885   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7886   int size;
7887
7888   size = getSize (operandType (result));
7889
7890   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7891
7892   /* We only handle certain easy cases so far. */
7893   if ((shCount != 0)
7894    && (shCount < (size * 8))
7895    && (size != 1)
7896    && (size != 2))
7897   {
7898       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7899       return FALSE;
7900   }
7901
7902   freeAsmop (right, NULL, ic, TRUE);
7903
7904   aopOp(left, ic, FALSE, FALSE);
7905   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7906
7907 #if 0 // debug spew
7908   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7909   {
7910         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7911         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7912         {
7913            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7914         }
7915   }
7916   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7917   {
7918         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7919         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7920         {
7921            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7922         }       
7923   }  
7924 #endif
7925   
7926 #if VIEW_SIZE
7927   emitcode ("; shift left ", "result %d, left %d", size,
7928             AOP_SIZE (left));
7929 #endif
7930
7931   /* I suppose that the left size >= result size */
7932   if (shCount == 0)
7933   {
7934         _startLazyDPSEvaluation();
7935         while (size--)
7936         {
7937           movLeft2Result (left, size, result, size, 0);
7938         }
7939         _endLazyDPSEvaluation();
7940   }
7941   else if (shCount >= (size * 8))
7942   {
7943     _startLazyDPSEvaluation();
7944     while (size--)
7945     {
7946       aopPut (AOP (result), zero, size);
7947     }
7948     _endLazyDPSEvaluation();
7949   }
7950   else
7951   {
7952       switch (size)
7953         {
7954         case 1:
7955           genlshOne (result, left, shCount);
7956           break;
7957
7958         case 2:
7959           genlshTwo (result, left, shCount);
7960           break;
7961 #if 0
7962         case 4:
7963           genlshFour (result, left, shCount);
7964           break;
7965 #endif
7966         default:
7967           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7968           break;
7969         }
7970     }
7971   freeAsmop (left, NULL, ic, TRUE);
7972   freeAsmop (result, NULL, ic, TRUE);
7973   return TRUE;
7974 }
7975 #endif
7976
7977 /*-----------------------------------------------------------------*/
7978 /* genLeftShift - generates code for left shifting                 */
7979 /*-----------------------------------------------------------------*/
7980 static void
7981 genLeftShift (iCode * ic)
7982 {
7983   operand *left, *right, *result;
7984   int size, offset;
7985   char *l;
7986   symbol *tlbl, *tlbl1;
7987
7988   D (emitcode (";", "genLeftShift "););
7989
7990   right = IC_RIGHT (ic);
7991   left = IC_LEFT (ic);
7992   result = IC_RESULT (ic);
7993
7994   aopOp (right, ic, FALSE, FALSE);
7995
7996
7997 #ifdef BETTER_LITERAL_SHIFT
7998   /* if the shift count is known then do it
7999      as efficiently as possible */
8000   if (AOP_TYPE (right) == AOP_LIT)
8001     {
8002       if (genLeftShiftLiteral (left, right, result, ic))
8003       {
8004         return;
8005       }
8006     }
8007 #endif
8008
8009   /* shift count is unknown then we have to form
8010      a loop get the loop count in B : Note: we take
8011      only the lower order byte since shifting
8012      more that 32 bits make no sense anyway, ( the
8013      largest size of an object can be only 32 bits ) */
8014
8015   if (AOP_TYPE (right) == AOP_LIT)
8016   {
8017       /* Really should be handled by genLeftShiftLiteral,
8018        * but since I'm too lazy to fix that today, at least we can make
8019        * some small improvement.
8020        */
8021        emitcode("mov", "b,#!constbyte",
8022                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8023   }
8024   else
8025   {
8026         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8027         emitcode ("inc", "b");
8028   }
8029   freeAsmop (right, NULL, ic, TRUE);
8030   aopOp (left, ic, FALSE, FALSE);
8031   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8032
8033   /* now move the left to the result if they are not the
8034      same */
8035   if (!sameRegs (AOP (left), AOP (result)) &&
8036       AOP_SIZE (result) > 1)
8037     {
8038
8039       size = AOP_SIZE (result);
8040       offset = 0;
8041       _startLazyDPSEvaluation ();
8042       while (size--)
8043         {
8044           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8045           if (*l == '@' && (IS_AOP_PREG (result)))
8046             {
8047
8048               emitcode ("mov", "a,%s", l);
8049               aopPut (AOP (result), "a", offset);
8050             }
8051           else
8052             aopPut (AOP (result), l, offset);
8053           offset++;
8054         }
8055       _endLazyDPSEvaluation ();
8056     }
8057
8058   tlbl = newiTempLabel (NULL);
8059   size = AOP_SIZE (result);
8060   offset = 0;
8061   tlbl1 = newiTempLabel (NULL);
8062
8063   /* if it is only one byte then */
8064   if (size == 1)
8065     {
8066       symbol *tlbl1 = newiTempLabel (NULL);
8067
8068       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8069       MOVA (l);
8070       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8071       emitcode ("", "!tlabeldef", tlbl->key + 100);
8072       emitcode ("add", "a,acc");
8073       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8074       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8075       aopPut (AOP (result), "a", 0);
8076       goto release;
8077     }
8078
8079   reAdjustPreg (AOP (result));
8080
8081   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8082   emitcode ("", "!tlabeldef", tlbl->key + 100);
8083   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8084   MOVA (l);
8085   emitcode ("add", "a,acc");
8086   aopPut (AOP (result), "a", offset++);
8087   _startLazyDPSEvaluation ();
8088   while (--size)
8089     {
8090       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8091       MOVA (l);
8092       emitcode ("rlc", "a");
8093       aopPut (AOP (result), "a", offset++);
8094     }
8095   _endLazyDPSEvaluation ();
8096   reAdjustPreg (AOP (result));
8097
8098   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8099   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8100 release:
8101   freeAsmop (left, NULL, ic, TRUE);
8102   freeAsmop (result, NULL, ic, TRUE);
8103 }
8104
8105 #ifdef BETTER_LITERAL_SHIFT
8106 /*-----------------------------------------------------------------*/
8107 /* genrshOne - right shift a one byte quantity by known count      */
8108 /*-----------------------------------------------------------------*/
8109 static void
8110 genrshOne (operand * result, operand * left,
8111            int shCount, int sign)
8112 {
8113   D (emitcode (";", "genrshOne"););
8114   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8115 }
8116 #endif
8117
8118 #ifdef BETTER_LITERAL_SHIFT
8119 /*-----------------------------------------------------------------*/
8120 /* genrshTwo - right shift two bytes by known amount != 0          */
8121 /*-----------------------------------------------------------------*/
8122 static void
8123 genrshTwo (operand * result, operand * left,
8124            int shCount, int sign)
8125 {
8126   D (emitcode (";", "genrshTwo"););
8127
8128   /* if shCount >= 8 */
8129   if (shCount >= 8)
8130     {
8131       shCount -= 8;
8132       _startLazyDPSEvaluation();
8133       if (shCount)
8134       {
8135         shiftR1Left2Result (left, MSB16, result, LSB,
8136                             shCount, sign);
8137       }                     
8138       else
8139       {
8140         movLeft2Result (left, MSB16, result, LSB, sign);
8141       }
8142       addSign (result, MSB16, sign);
8143       _endLazyDPSEvaluation();
8144     }
8145
8146   /*  1 <= shCount <= 7 */
8147   else
8148   {
8149     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8150   }
8151 }
8152 #endif
8153
8154 #if 0
8155 //REMOVE ME!!!
8156 /*-----------------------------------------------------------------*/
8157 /* shiftRLong - shift right one long from left to result           */
8158 /* offl = LSB or MSB16                                             */
8159 /*-----------------------------------------------------------------*/
8160 static void
8161 shiftRLong (operand * left, int offl,
8162             operand * result, int sign)
8163 {
8164   int isSameRegs=sameRegs(AOP(left),AOP(result));
8165
8166   if (isSameRegs && offl>1) {
8167     // we are in big trouble, but this shouldn't happen
8168     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8169   }
8170
8171   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8172   
8173   if (offl==MSB16) {
8174     // shift is > 8
8175     if (sign) {
8176       emitcode ("rlc", "a");
8177       emitcode ("subb", "a,acc");
8178       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8179     } else {
8180       aopPut (AOP(result), zero, MSB32);
8181     }
8182   }
8183
8184   if (!sign) {
8185     emitcode ("clr", "c");
8186   } else {
8187     emitcode ("mov", "c,acc.7");
8188   }
8189
8190   emitcode ("rrc", "a");
8191
8192   if (isSameRegs && offl==MSB16) {
8193     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8194   } else {
8195     aopPut (AOP (result), "a", MSB32);
8196     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8197   }
8198
8199   emitcode ("rrc", "a");
8200   if (isSameRegs && offl==1) {
8201     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8202   } else {
8203     aopPut (AOP (result), "a", MSB24);
8204     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8205   }
8206   emitcode ("rrc", "a");
8207   aopPut (AOP (result), "a", MSB16 - offl);
8208
8209   if (offl == LSB)
8210     {
8211       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8212       emitcode ("rrc", "a");
8213       aopPut (AOP (result), "a", LSB);
8214     }
8215 }
8216 #endif
8217
8218 #if 0
8219 //REMOVE ME!!!
8220 /*-----------------------------------------------------------------*/
8221 /* genrshFour - shift four byte by a known amount != 0             */
8222 /*-----------------------------------------------------------------*/
8223 static void
8224 genrshFour (operand * result, operand * left,
8225             int shCount, int sign)
8226 {
8227   D (emitcode (";", "genrshFour");
8228     );
8229
8230   /* if shifting more that 3 bytes */
8231   if (shCount >= 24)
8232     {
8233       shCount -= 24;
8234       if (shCount)
8235         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8236       else
8237         movLeft2Result (left, MSB32, result, LSB, sign);
8238       addSign (result, MSB16, sign);
8239     }
8240   else if (shCount >= 16)
8241     {
8242       shCount -= 16;
8243       if (shCount)
8244         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8245       else
8246         {
8247           movLeft2Result (left, MSB24, result, LSB, 0);
8248           movLeft2Result (left, MSB32, result, MSB16, sign);
8249         }
8250       addSign (result, MSB24, sign);
8251     }
8252   else if (shCount >= 8)
8253     {
8254       shCount -= 8;
8255       if (shCount == 1)
8256         shiftRLong (left, MSB16, result, sign);
8257       else if (shCount == 0)
8258         {
8259           movLeft2Result (left, MSB16, result, LSB, 0);
8260           movLeft2Result (left, MSB24, result, MSB16, 0);
8261           movLeft2Result (left, MSB32, result, MSB24, sign);
8262           addSign (result, MSB32, sign);
8263         }
8264       else
8265         {
8266           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8267           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8268           /* the last shift is signed */
8269           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8270           addSign (result, MSB32, sign);
8271         }
8272     }
8273   else
8274     {                           /* 1 <= shCount <= 7 */
8275       if (shCount <= 2)
8276         {
8277           shiftRLong (left, LSB, result, sign);
8278           if (shCount == 2)
8279             shiftRLong (result, LSB, result, sign);
8280         }
8281       else
8282         {
8283           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8284           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8285           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8286         }
8287     }
8288 }
8289 #endif
8290
8291 #ifdef BETTER_LITERAL_SHIFT
8292 /*-----------------------------------------------------------------*/
8293 /* genRightShiftLiteral - right shifting by known count            */
8294 /*-----------------------------------------------------------------*/
8295 static bool
8296 genRightShiftLiteral (operand * left,
8297                       operand * right,
8298                       operand * result,
8299                       iCode * ic,
8300                       int sign)
8301 {
8302   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8303   int size;
8304
8305   size = getSize (operandType (result));
8306
8307   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8308
8309   /* We only handle certain easy cases so far. */
8310   if ((shCount != 0)
8311    && (shCount < (size * 8))
8312    && (size != 1)
8313    && (size != 2))
8314   {
8315       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8316       return FALSE;
8317   }
8318
8319   freeAsmop (right, NULL, ic, TRUE);
8320
8321   aopOp (left, ic, FALSE, FALSE);
8322   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8323
8324 #if VIEW_SIZE
8325   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8326             AOP_SIZE (left));
8327 #endif
8328
8329   /* test the LEFT size !!! */
8330
8331   /* I suppose that the left size >= result size */
8332   if (shCount == 0)
8333   {
8334       size = getDataSize (result);
8335       _startLazyDPSEvaluation();
8336       while (size--)
8337       {
8338         movLeft2Result (left, size, result, size, 0);
8339       }
8340       _endLazyDPSEvaluation();
8341   }
8342   else if (shCount >= (size * 8))
8343     {
8344       if (sign)
8345       {
8346         /* get sign in acc.7 */
8347         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8348       }
8349       addSign (result, LSB, sign);
8350     }
8351   else
8352     {
8353       switch (size)
8354         {
8355         case 1:
8356           genrshOne (result, left, shCount, sign);
8357           break;
8358
8359         case 2:
8360           genrshTwo (result, left, shCount, sign);
8361           break;
8362 #if 0
8363         case 4:
8364           genrshFour (result, left, shCount, sign);
8365           break;
8366 #endif    
8367         default:
8368           break;
8369         }
8370
8371       freeAsmop (left, NULL, ic, TRUE);
8372       freeAsmop (result, NULL, ic, TRUE);
8373     }
8374     return TRUE;
8375 }
8376 #endif
8377
8378 /*-----------------------------------------------------------------*/
8379 /* genSignedRightShift - right shift of signed number              */
8380 /*-----------------------------------------------------------------*/
8381 static void
8382 genSignedRightShift (iCode * ic)
8383 {
8384   operand *right, *left, *result;
8385   int size, offset;
8386   char *l;
8387   symbol *tlbl, *tlbl1;
8388
8389   D (emitcode (";", "genSignedRightShift "););
8390
8391   /* we do it the hard way put the shift count in b
8392      and loop thru preserving the sign */
8393
8394   right = IC_RIGHT (ic);
8395   left = IC_LEFT (ic);
8396   result = IC_RESULT (ic);
8397
8398   aopOp (right, ic, FALSE, FALSE);
8399
8400 #ifdef BETTER_LITERAL_SHIFT
8401   if (AOP_TYPE (right) == AOP_LIT)
8402     {
8403       if (genRightShiftLiteral (left, right, result, ic, 1))
8404       {
8405         return;
8406       }
8407     }
8408 #endif
8409   /* shift count is unknown then we have to form
8410      a loop get the loop count in B : Note: we take
8411      only the lower order byte since shifting
8412      more that 32 bits make no sense anyway, ( the
8413      largest size of an object can be only 32 bits ) */
8414
8415   if (AOP_TYPE (right) == AOP_LIT)
8416   {
8417       /* Really should be handled by genRightShiftLiteral,
8418        * but since I'm too lazy to fix that today, at least we can make
8419        * some small improvement.
8420        */
8421        emitcode("mov", "b,#!constbyte",
8422                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8423   }
8424   else
8425   {
8426         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8427         emitcode ("inc", "b");
8428   }
8429   freeAsmop (right, NULL, ic, TRUE);
8430   aopOp (left, ic, FALSE, FALSE);
8431   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8432
8433   /* now move the left to the result if they are not the
8434      same */
8435   if (!sameRegs (AOP (left), AOP (result)) &&
8436       AOP_SIZE (result) > 1)
8437     {
8438
8439       size = AOP_SIZE (result);
8440       offset = 0;
8441       _startLazyDPSEvaluation ();
8442       while (size--)
8443         {
8444           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8445           if (*l == '@' && IS_AOP_PREG (result))
8446             {
8447
8448               emitcode ("mov", "a,%s", l);
8449               aopPut (AOP (result), "a", offset);
8450             }
8451           else
8452             aopPut (AOP (result), l, offset);
8453           offset++;
8454         }
8455       _endLazyDPSEvaluation ();
8456     }
8457
8458   /* mov the highest order bit to OVR */
8459   tlbl = newiTempLabel (NULL);
8460   tlbl1 = newiTempLabel (NULL);
8461
8462   size = AOP_SIZE (result);
8463   offset = size - 1;
8464   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8465   emitcode ("rlc", "a");
8466   emitcode ("mov", "ov,c");
8467   /* if it is only one byte then */
8468   if (size == 1)
8469     {
8470       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8471       MOVA (l);
8472       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8473       emitcode ("", "!tlabeldef", tlbl->key + 100);
8474       emitcode ("mov", "c,ov");
8475       emitcode ("rrc", "a");
8476       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8477       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8478       aopPut (AOP (result), "a", 0);
8479       goto release;
8480     }
8481
8482   reAdjustPreg (AOP (result));
8483   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8484   emitcode ("", "!tlabeldef", tlbl->key + 100);
8485   emitcode ("mov", "c,ov");
8486   _startLazyDPSEvaluation ();
8487   while (size--)
8488     {
8489       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8490       MOVA (l);
8491       emitcode ("rrc", "a");
8492       aopPut (AOP (result), "a", offset--);
8493     }
8494   _endLazyDPSEvaluation ();
8495   reAdjustPreg (AOP (result));
8496   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8497   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8498
8499 release:
8500   freeAsmop (left, NULL, ic, TRUE);
8501   freeAsmop (result, NULL, ic, TRUE);
8502 }
8503
8504 /*-----------------------------------------------------------------*/
8505 /* genRightShift - generate code for right shifting                */
8506 /*-----------------------------------------------------------------*/
8507 static void
8508 genRightShift (iCode * ic)
8509 {
8510   operand *right, *left, *result;
8511   sym_link *retype;
8512   int size, offset;
8513   char *l;
8514   symbol *tlbl, *tlbl1;
8515
8516   D (emitcode (";", "genRightShift "););
8517
8518   /* if signed then we do it the hard way preserve the
8519      sign bit moving it inwards */
8520   retype = getSpec (operandType (IC_RESULT (ic)));
8521
8522   if (!SPEC_USIGN (retype))
8523     {
8524       genSignedRightShift (ic);
8525       return;
8526     }
8527
8528   /* signed & unsigned types are treated the same : i.e. the
8529      signed is NOT propagated inwards : quoting from the
8530      ANSI - standard : "for E1 >> E2, is equivalent to division
8531      by 2**E2 if unsigned or if it has a non-negative value,
8532      otherwise the result is implementation defined ", MY definition
8533      is that the sign does not get propagated */
8534
8535   right = IC_RIGHT (ic);
8536   left = IC_LEFT (ic);
8537   result = IC_RESULT (ic);
8538
8539   aopOp (right, ic, FALSE, FALSE);
8540
8541 #ifdef BETTER_LITERAL_SHIFT
8542   /* if the shift count is known then do it
8543      as efficiently as possible */
8544   if (AOP_TYPE (right) == AOP_LIT)
8545     {
8546       if (genRightShiftLiteral (left, right, result, ic, 0))
8547       {
8548         return;
8549       }
8550     }
8551 #endif
8552
8553   /* shift count is unknown then we have to form
8554      a loop get the loop count in B : Note: we take
8555      only the lower order byte since shifting
8556      more that 32 bits make no sense anyway, ( the
8557      largest size of an object can be only 32 bits ) */
8558   
8559   if (AOP_TYPE (right) == AOP_LIT)
8560   {
8561       /* Really should be handled by genRightShiftLiteral,
8562        * but since I'm too lazy to fix that today, at least we can make
8563        * some small improvement.
8564        */
8565        emitcode("mov", "b,#!constbyte",
8566                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8567   }
8568   else
8569   {
8570         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8571         emitcode ("inc", "b");
8572   }
8573   freeAsmop (right, NULL, ic, TRUE);
8574   aopOp (left, ic, FALSE, FALSE);
8575   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8576
8577   /* now move the left to the result if they are not the
8578      same */
8579   if (!sameRegs (AOP (left), AOP (result)) &&
8580       AOP_SIZE (result) > 1)
8581     {
8582
8583       size = AOP_SIZE (result);
8584       offset = 0;
8585       _startLazyDPSEvaluation ();
8586       while (size--)
8587         {
8588           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8589           if (*l == '@' && IS_AOP_PREG (result))
8590             {
8591
8592               emitcode ("mov", "a,%s", l);
8593               aopPut (AOP (result), "a", offset);
8594             }
8595           else
8596             aopPut (AOP (result), l, offset);
8597           offset++;
8598         }
8599       _endLazyDPSEvaluation ();
8600     }
8601
8602   tlbl = newiTempLabel (NULL);
8603   tlbl1 = newiTempLabel (NULL);
8604   size = AOP_SIZE (result);
8605   offset = size - 1;
8606
8607   /* if it is only one byte then */
8608   if (size == 1)
8609     {
8610       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8611       MOVA (l);
8612       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8613       emitcode ("", "!tlabeldef", tlbl->key + 100);
8614       CLRC;
8615       emitcode ("rrc", "a");
8616       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8617       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8618       aopPut (AOP (result), "a", 0);
8619       goto release;
8620     }
8621
8622   reAdjustPreg (AOP (result));
8623   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8624   emitcode ("", "!tlabeldef", tlbl->key + 100);
8625   CLRC;
8626   _startLazyDPSEvaluation ();
8627   while (size--)
8628     {
8629       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8630       MOVA (l);
8631       emitcode ("rrc", "a");
8632       aopPut (AOP (result), "a", offset--);
8633     }
8634   _endLazyDPSEvaluation ();
8635   reAdjustPreg (AOP (result));
8636
8637   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8638   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8639
8640 release:
8641   freeAsmop (left, NULL, ic, TRUE);
8642   freeAsmop (result, NULL, ic, TRUE);
8643 }
8644
8645 /*-----------------------------------------------------------------*/
8646 /* genUnpackBits - generates code for unpacking bits               */
8647 /*-----------------------------------------------------------------*/
8648 static void
8649 genUnpackBits (operand * result, char *rname, int ptype)
8650 {
8651   int shCnt;
8652   int rlen = 0;
8653   sym_link *etype;
8654   int offset = 0;
8655
8656   D (emitcode (";", "genUnpackBits ");
8657     );
8658
8659   etype = getSpec (operandType (result));
8660
8661   /* read the first byte  */
8662   switch (ptype)
8663     {
8664
8665     case POINTER:
8666     case IPOINTER:
8667       emitcode ("mov", "a,@%s", rname);
8668       break;
8669
8670     case PPOINTER:
8671       emitcode ("movx", "a,@%s", rname);
8672       break;
8673
8674     case FPOINTER:
8675       emitcode ("movx", "a,@dptr");
8676       break;
8677
8678     case CPOINTER:
8679       emitcode ("clr", "a");
8680       emitcode ("movc", "a,@a+dptr");
8681       break;
8682
8683     case GPOINTER:
8684       emitcode ("lcall", "__gptrget");
8685       break;
8686     }
8687
8688   /* if we have bitdisplacement then it fits   */
8689   /* into this byte completely or if length is */
8690   /* less than a byte                          */
8691   if ((shCnt = SPEC_BSTR (etype)) ||
8692       (SPEC_BLEN (etype) <= 8))
8693     {
8694
8695       /* shift right acc */
8696       AccRsh (shCnt);
8697
8698       emitcode ("anl", "a,#!constbyte",
8699                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8700       aopPut (AOP (result), "a", offset);
8701       return;
8702     }
8703
8704   /* bit field did not fit in a byte  */
8705   rlen = SPEC_BLEN (etype) - 8;
8706   aopPut (AOP (result), "a", offset++);
8707
8708   while (1)
8709     {
8710
8711       switch (ptype)
8712         {
8713         case POINTER:
8714         case IPOINTER:
8715           emitcode ("inc", "%s", rname);
8716           emitcode ("mov", "a,@%s", rname);
8717           break;
8718
8719         case PPOINTER:
8720           emitcode ("inc", "%s", rname);
8721           emitcode ("movx", "a,@%s", rname);
8722           break;
8723
8724         case FPOINTER:
8725           emitcode ("inc", "dptr");
8726           emitcode ("movx", "a,@dptr");
8727           break;
8728
8729         case CPOINTER:
8730           emitcode ("clr", "a");
8731           emitcode ("inc", "dptr");
8732           emitcode ("movc", "a,@a+dptr");
8733           break;
8734
8735         case GPOINTER:
8736           emitcode ("inc", "dptr");
8737           emitcode ("lcall", "__gptrget");
8738           break;
8739         }
8740
8741       rlen -= 8;
8742       /* if we are done */
8743       if (rlen < 8)
8744         break;
8745
8746       aopPut (AOP (result), "a", offset++);
8747
8748     }
8749
8750   if (rlen)
8751     {
8752       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8753       aopPut (AOP (result), "a", offset);
8754     }
8755
8756   return;
8757 }
8758
8759
8760 /*-----------------------------------------------------------------*/
8761 /* genDataPointerGet - generates code when ptr offset is known     */
8762 /*-----------------------------------------------------------------*/
8763 static void
8764 genDataPointerGet (operand * left,
8765                    operand * result,
8766                    iCode * ic)
8767 {
8768   char *l;
8769   char buffer[256];
8770   int size, offset = 0;
8771   aopOp (result, ic, TRUE, FALSE);
8772
8773   /* get the string representation of the name */
8774   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8775   size = AOP_SIZE (result);
8776   _startLazyDPSEvaluation ();
8777   while (size--)
8778     {
8779       if (offset)
8780         sprintf (buffer, "(%s + %d)", l + 1, offset);
8781       else
8782         sprintf (buffer, "%s", l + 1);
8783       aopPut (AOP (result), buffer, offset++);
8784     }
8785   _endLazyDPSEvaluation ();
8786
8787   freeAsmop (left, NULL, ic, TRUE);
8788   freeAsmop (result, NULL, ic, TRUE);
8789 }
8790
8791 /*-----------------------------------------------------------------*/
8792 /* genNearPointerGet - emitcode for near pointer fetch             */
8793 /*-----------------------------------------------------------------*/
8794 static void
8795 genNearPointerGet (operand * left,
8796                    operand * result,
8797                    iCode * ic,
8798                    iCode *pi)
8799 {
8800   asmop *aop = NULL;
8801   regs *preg = NULL;
8802   char *rname;
8803   sym_link *rtype, *retype, *letype;
8804   sym_link *ltype = operandType (left);
8805   char buffer[80];
8806
8807   rtype = operandType (result);
8808   retype = getSpec (rtype);
8809   letype = getSpec (ltype);
8810
8811   aopOp (left, ic, FALSE, FALSE);
8812
8813   /* if left is rematerialisable and
8814      result is not bit variable type and
8815      the left is pointer to data space i.e
8816      lower 128 bytes of space */
8817   if (AOP_TYPE (left) == AOP_IMMD &&
8818       !IS_BITVAR (retype) &&
8819       !IS_BITVAR (letype) &&
8820       DCL_TYPE (ltype) == POINTER)
8821     {
8822       genDataPointerGet (left, result, ic);
8823       return;
8824     }
8825
8826   /* if the value is already in a pointer register
8827      then don't need anything more */
8828   if (!AOP_INPREG (AOP (left)))
8829     {
8830       /* otherwise get a free pointer register */
8831       aop = newAsmop (0);
8832       preg = getFreePtr (ic, &aop, FALSE);
8833       emitcode ("mov", "%s,%s",
8834                 preg->name,
8835                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8836       rname = preg->name;
8837     }
8838   else
8839     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8840
8841   freeAsmop (left, NULL, ic, TRUE);
8842   aopOp (result, ic, FALSE, FALSE);
8843
8844   /* if bitfield then unpack the bits */
8845   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8846     genUnpackBits (result, rname, POINTER);
8847   else
8848     {
8849       /* we have can just get the values */
8850       int size = AOP_SIZE (result);
8851       int offset = 0;
8852
8853       while (size--)
8854         {
8855           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8856             {
8857
8858               emitcode ("mov", "a,@%s", rname);
8859               aopPut (AOP (result), "a", offset);
8860             }
8861           else
8862             {
8863               sprintf (buffer, "@%s", rname);
8864               aopPut (AOP (result), buffer, offset);
8865             }
8866           offset++;
8867           if (size || pi)
8868             emitcode ("inc", "%s", rname);
8869         }
8870     }
8871
8872   /* now some housekeeping stuff */
8873   if (aop)
8874     {
8875       /* we had to allocate for this iCode */
8876       if (pi) { /* post increment present */
8877         aopPut(AOP ( left ),rname,0);
8878       }
8879       freeAsmop (NULL, aop, ic, TRUE);
8880     }
8881   else
8882     {
8883       /* we did not allocate which means left
8884          already in a pointer register, then
8885          if size > 0 && this could be used again
8886          we have to point it back to where it
8887          belongs */
8888       if (AOP_SIZE (result) > 1 &&
8889           !OP_SYMBOL (left)->remat &&
8890           (OP_SYMBOL (left)->liveTo > ic->seq ||
8891            ic->depth) &&
8892           !pi)
8893         {
8894           int size = AOP_SIZE (result) - 1;
8895           while (size--)
8896             emitcode ("dec", "%s", rname);
8897         }
8898     }
8899
8900   /* done */
8901   freeAsmop (result, NULL, ic, TRUE);
8902   if (pi) pi->generated = 1;
8903 }
8904
8905 /*-----------------------------------------------------------------*/
8906 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8907 /*-----------------------------------------------------------------*/
8908 static void
8909 genPagedPointerGet (operand * left,
8910                     operand * result,
8911                     iCode * ic,
8912                     iCode * pi)
8913 {
8914   asmop *aop = NULL;
8915   regs *preg = NULL;
8916   char *rname;
8917   sym_link *rtype, *retype, *letype;
8918
8919   rtype = operandType (result);
8920   retype = getSpec (rtype);
8921   letype = getSpec (operandType (left));
8922   aopOp (left, ic, FALSE, FALSE);
8923
8924   /* if the value is already in a pointer register
8925      then don't need anything more */
8926   if (!AOP_INPREG (AOP (left)))
8927     {
8928       /* otherwise get a free pointer register */
8929       aop = newAsmop (0);
8930       preg = getFreePtr (ic, &aop, FALSE);
8931       emitcode ("mov", "%s,%s",
8932                 preg->name,
8933                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8934       rname = preg->name;
8935     }
8936   else
8937     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8938
8939   freeAsmop (left, NULL, ic, TRUE);
8940   aopOp (result, ic, FALSE, FALSE);
8941
8942   /* if bitfield then unpack the bits */
8943   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8944     genUnpackBits (result, rname, PPOINTER);
8945   else
8946     {
8947       /* we have can just get the values */
8948       int size = AOP_SIZE (result);
8949       int offset = 0;
8950
8951       while (size--)
8952         {
8953
8954           emitcode ("movx", "a,@%s", rname);
8955           aopPut (AOP (result), "a", offset);
8956
8957           offset++;
8958
8959           if (size || pi)
8960             emitcode ("inc", "%s", rname);
8961         }
8962     }
8963
8964   /* now some housekeeping stuff */
8965   if (aop)
8966     {
8967       /* we had to allocate for this iCode */
8968       if (pi) aopPut ( AOP (left), rname, 0);
8969       freeAsmop (NULL, aop, ic, TRUE);
8970     }
8971   else
8972     {
8973       /* we did not allocate which means left
8974          already in a pointer register, then
8975          if size > 0 && this could be used again
8976          we have to point it back to where it
8977          belongs */
8978       if (AOP_SIZE (result) > 1 &&
8979           !OP_SYMBOL (left)->remat &&
8980           (OP_SYMBOL (left)->liveTo > ic->seq ||
8981            ic->depth) &&
8982           !pi)
8983         {
8984           int size = AOP_SIZE (result) - 1;
8985           while (size--)
8986             emitcode ("dec", "%s", rname);
8987         }
8988     }
8989
8990   /* done */
8991   freeAsmop (result, NULL, ic, TRUE);
8992   if (pi) pi->generated = 1;
8993 }
8994
8995 /*-----------------------------------------------------------------*/
8996 /* genFarPointerGet - gget value from far space                    */
8997 /*-----------------------------------------------------------------*/
8998 static void
8999 genFarPointerGet (operand * left,
9000                   operand * result, iCode * ic, iCode *pi)
9001 {
9002     int size, offset, dopi=1;
9003   sym_link *retype = getSpec (operandType (result));
9004   sym_link *letype = getSpec (operandType (left));
9005   D (emitcode (";", "genFarPointerGet");
9006     );
9007
9008   aopOp (left, ic, FALSE, FALSE);
9009
9010   /* if the operand is already in dptr
9011      then we do nothing else we move the value to dptr */
9012   if (AOP_TYPE (left) != AOP_STR)
9013     {
9014       /* if this is remateriazable */
9015       if (AOP_TYPE (left) == AOP_IMMD)
9016         {
9017           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9018         }
9019       else
9020         {
9021           /* we need to get it byte by byte */
9022           _startLazyDPSEvaluation ();
9023           if (AOP_TYPE (left) != AOP_DPTR)
9024             {
9025               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9026               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9027               if (options.model == MODEL_FLAT24)
9028                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9029             }
9030           else
9031             {
9032               /* We need to generate a load to DPTR indirect through DPTR. */
9033               D (emitcode (";", "genFarPointerGet -- indirection special case.");
9034                 );
9035               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9036               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9037               if (options.model == MODEL_FLAT24)
9038                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9039               emitcode ("pop", "dph");
9040               emitcode ("pop", "dpl");
9041               dopi =0;
9042             }
9043           _endLazyDPSEvaluation ();
9044         }
9045     }
9046   /* so dptr know contains the address */
9047   aopOp (result, ic, FALSE, TRUE);
9048
9049   /* if bit then unpack */
9050   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9051     genUnpackBits (result, "dptr", FPOINTER);
9052   else
9053     {
9054       size = AOP_SIZE (result);
9055       offset = 0;
9056
9057       _startLazyDPSEvaluation ();
9058       while (size--)
9059         {
9060
9061           genSetDPTR (0);
9062           _flushLazyDPS ();
9063
9064           emitcode ("movx", "a,@dptr");
9065           if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9066             emitcode ("inc", "dptr");
9067
9068           aopPut (AOP (result), "a", offset++);
9069         }
9070       _endLazyDPSEvaluation ();
9071     }
9072   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9073     aopPut ( AOP (left), "dpl", 0);
9074     aopPut ( AOP (left), "dph", 1);
9075     if (options.model == MODEL_FLAT24)
9076             aopPut ( AOP (left), "dpx", 2);
9077     pi->generated = 1;
9078   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9079              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9080       
9081       size = AOP_SIZE (result) - 1;
9082       while (size--) emitcode ("lcall","__decdptr");
9083   }
9084
9085   freeAsmop (left, NULL, ic, TRUE);
9086   freeAsmop (result, NULL, ic, TRUE);
9087 }
9088
9089 /*-----------------------------------------------------------------*/
9090 /* emitcodePointerGet - gget value from code space                  */
9091 /*-----------------------------------------------------------------*/
9092 static void
9093 emitcodePointerGet (operand * left,
9094                     operand * result, iCode * ic, iCode *pi)
9095 {
9096   int size, offset, dopi=1;
9097   sym_link *retype = getSpec (operandType (result));
9098
9099   aopOp (left, ic, FALSE, FALSE);
9100
9101   /* if the operand is already in dptr
9102      then we do nothing else we move the value to dptr */
9103   if (AOP_TYPE (left) != AOP_STR)
9104     {
9105       /* if this is remateriazable */
9106       if (AOP_TYPE (left) == AOP_IMMD)
9107         {
9108           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9109         }
9110       else
9111         {                       /* we need to get it byte by byte */
9112           _startLazyDPSEvaluation ();
9113           if (AOP_TYPE (left) != AOP_DPTR)
9114             {
9115               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9116               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9117               if (options.model == MODEL_FLAT24)
9118                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9119             }
9120           else
9121             {
9122               /* We need to generate a load to DPTR indirect through DPTR. */
9123               D (emitcode (";", "gencodePointerGet -- indirection special case.");
9124                 );
9125               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9126               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9127               if (options.model == MODEL_FLAT24)
9128                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9129               emitcode ("pop", "dph");
9130               emitcode ("pop", "dpl");
9131               dopi=0;
9132             }
9133           _endLazyDPSEvaluation ();
9134         }
9135     }
9136   /* so dptr know contains the address */
9137   aopOp (result, ic, FALSE, TRUE);
9138
9139   /* if bit then unpack */
9140   if (IS_BITVAR (retype))
9141     genUnpackBits (result, "dptr", CPOINTER);
9142   else
9143     {
9144       size = AOP_SIZE (result);
9145       offset = 0;
9146
9147       _startLazyDPSEvaluation ();
9148       while (size--)
9149         {
9150           genSetDPTR (0);
9151           _flushLazyDPS ();
9152
9153           emitcode ("clr", "a");
9154           emitcode ("movc", "a,@a+dptr");
9155           if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9156             emitcode ("inc", "dptr");
9157           aopPut (AOP (result), "a", offset++);
9158         }
9159       _endLazyDPSEvaluation ();
9160     }
9161   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9162       aopPut ( AOP (left), "dpl", 0);
9163       aopPut ( AOP (left), "dph", 1);
9164       if (options.model == MODEL_FLAT24)
9165           aopPut ( AOP (left), "dpx", 2);
9166       pi->generated = 1;
9167   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9168              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9169       
9170       size = AOP_SIZE (result) - 1;
9171       while (size--) emitcode ("lcall","__decdptr");
9172   }
9173   
9174   freeAsmop (left, NULL, ic, TRUE);
9175   freeAsmop (result, NULL, ic, TRUE);
9176 }
9177
9178 /*-----------------------------------------------------------------*/
9179 /* genGenPointerGet - gget value from generic pointer space        */
9180 /*-----------------------------------------------------------------*/
9181 static void
9182 genGenPointerGet (operand * left,
9183                   operand * result, iCode * ic, iCode * pi)
9184 {
9185   int size, offset;
9186   sym_link *retype = getSpec (operandType (result));
9187   sym_link *letype = getSpec (operandType (left));
9188
9189   D (emitcode (";", "genGenPointerGet "); );
9190
9191   aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9192
9193   /* if the operand is already in dptr
9194      then we do nothing else we move the value to dptr */
9195   if (AOP_TYPE (left) != AOP_STR)
9196     {
9197       /* if this is remateriazable */
9198       if (AOP_TYPE (left) == AOP_IMMD)
9199         {
9200           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9201           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9202                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9203           else
9204                   emitcode ("mov", "b,#%d", pointerCode (retype));
9205         }
9206       else
9207         {                       /* we need to get it byte by byte */
9208           _startLazyDPSEvaluation ();
9209           if (AOP(left)->type==AOP_DPTR2) {
9210             char *l;
9211             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9212             genSetDPTR(0);
9213             _flushLazyDPS();
9214             emitcode ("mov", "dpl,%s", l);
9215             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9216             genSetDPTR(0);
9217             _flushLazyDPS();
9218             emitcode ("mov", "dph,%s", l);
9219             if (options.model == MODEL_FLAT24) {
9220               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9221               genSetDPTR(0);
9222               _flushLazyDPS();
9223               emitcode ("mov", "dpx,%s", l);
9224               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9225             } else {
9226               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9227             }
9228           } else {
9229             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9230             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9231             if (options.model == MODEL_FLAT24) {
9232               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9233               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9234             } else {
9235               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9236             }
9237           }
9238           _endLazyDPSEvaluation ();
9239         }
9240     }
9241   /* so dptr know contains the address */
9242   aopOp (result, ic, FALSE, TRUE);
9243
9244   /* if bit then unpack */
9245   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9246     genUnpackBits (result, "dptr", GPOINTER);
9247   else
9248     {
9249       size = AOP_SIZE (result);
9250       offset = 0;
9251
9252       while (size--)
9253         {
9254           emitcode ("lcall", "__gptrget");
9255           aopPut (AOP (result), "a", offset++);
9256           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9257             emitcode ("inc", "dptr");
9258         }
9259     }
9260
9261   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9262     aopPut ( AOP (left), "dpl", 0);
9263     aopPut ( AOP (left), "dph", 1);
9264     if (options.model == MODEL_FLAT24) {
9265         aopPut ( AOP (left), "dpx", 2);
9266         aopPut ( AOP (left), "b", 3);   
9267     } else  aopPut ( AOP (left), "b", 2);       
9268     pi->generated = 1;
9269   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9270              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9271       
9272       size = AOP_SIZE (result) - 1;
9273       while (size--) emitcode ("lcall","__decdptr");
9274   }
9275
9276   freeAsmop (left, NULL, ic, TRUE);
9277   freeAsmop (result, NULL, ic, TRUE);
9278 }
9279
9280 /*-----------------------------------------------------------------*/
9281 /* genPointerGet - generate code for pointer get                   */
9282 /*-----------------------------------------------------------------*/
9283 static void
9284 genPointerGet (iCode * ic, iCode *pi)
9285 {
9286   operand *left, *result;
9287   sym_link *type, *etype;
9288   int p_type;
9289
9290   D (emitcode (";", "genPointerGet ");
9291     );
9292
9293   left = IC_LEFT (ic);
9294   result = IC_RESULT (ic);
9295
9296   /* depending on the type of pointer we need to
9297      move it to the correct pointer register */
9298   type = operandType (left);
9299   etype = getSpec (type);
9300   /* if left is of type of pointer then it is simple */
9301   if (IS_PTR (type) && !IS_FUNC (type->next))
9302     p_type = DCL_TYPE (type);
9303   else
9304     {
9305       /* we have to go by the storage class */
9306       p_type = PTR_TYPE (SPEC_OCLS (etype));
9307     }
9308   /* special case when cast remat */
9309   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9310       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9311           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9312           type =   type = operandType (left);
9313           p_type = DCL_TYPE (type);
9314   }
9315   /* now that we have the pointer type we assign
9316      the pointer values */
9317   switch (p_type)
9318     {
9319
9320     case POINTER:
9321     case IPOINTER:
9322       genNearPointerGet (left, result, ic, pi);
9323       break;
9324
9325     case PPOINTER:
9326       genPagedPointerGet (left, result, ic, pi);
9327       break;
9328
9329     case FPOINTER:
9330       genFarPointerGet (left, result, ic, pi);
9331       break;
9332
9333     case CPOINTER:
9334       emitcodePointerGet (left, result, ic, pi);
9335       break;
9336
9337     case GPOINTER:
9338       genGenPointerGet (left, result, ic, pi);
9339       break;
9340     }
9341
9342 }
9343
9344 /*-----------------------------------------------------------------*/
9345 /* genPackBits - generates code for packed bit storage             */
9346 /*-----------------------------------------------------------------*/
9347 static void
9348 genPackBits (sym_link * etype,
9349              operand * right,
9350              char *rname, int p_type)
9351 {
9352   int shCount = 0;
9353   int offset = 0;
9354   int rLen = 0;
9355   int blen, bstr;
9356   char *l;
9357
9358   blen = SPEC_BLEN (etype);
9359   bstr = SPEC_BSTR (etype);
9360
9361   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9362   MOVA (l);
9363
9364   /* if the bit lenth is less than or    */
9365   /* it exactly fits a byte then         */
9366   if (SPEC_BLEN (etype) <= 8)
9367     {
9368       shCount = SPEC_BSTR (etype);
9369
9370       /* shift left acc */
9371       AccLsh (shCount);
9372
9373       if (SPEC_BLEN (etype) < 8)
9374         {                       /* if smaller than a byte */
9375
9376
9377           switch (p_type)
9378             {
9379             case POINTER:
9380               emitcode ("mov", "b,a");
9381               emitcode ("mov", "a,@%s", rname);
9382               break;
9383
9384             case FPOINTER:
9385               emitcode ("mov", "b,a");
9386               emitcode ("movx", "a,@dptr");
9387               break;
9388
9389             case GPOINTER:
9390               emitcode ("push", "b");
9391               emitcode ("push", "acc");
9392               emitcode ("lcall", "__gptrget");
9393               emitcode ("pop", "b");
9394               break;
9395             }
9396
9397           emitcode ("anl", "a,#!constbyte", (unsigned char)
9398                     ((unsigned char) (0xFF << (blen + bstr)) |
9399                      (unsigned char) (0xFF >> (8 - bstr))));
9400           emitcode ("orl", "a,b");
9401           if (p_type == GPOINTER)
9402             emitcode ("pop", "b");
9403         }
9404     }
9405
9406   switch (p_type)
9407     {
9408     case POINTER:
9409       emitcode ("mov", "@%s,a", rname);
9410       break;
9411
9412     case FPOINTER:
9413       emitcode ("movx", "@dptr,a");
9414       break;
9415
9416     case GPOINTER:
9417       emitcode ("lcall", "__gptrput");
9418       break;
9419     }
9420
9421   /* if we r done */
9422   if (SPEC_BLEN (etype) <= 8)
9423     return;
9424
9425   emitcode ("inc", "%s", rname);
9426   rLen = SPEC_BLEN (etype);
9427
9428   /* now generate for lengths greater than one byte */
9429   while (1)
9430     {
9431
9432       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9433
9434       rLen -= 8;
9435       if (rLen < 8)
9436         break;
9437
9438       switch (p_type)
9439         {
9440         case POINTER:
9441           if (*l == '@')
9442             {
9443               MOVA (l);
9444               emitcode ("mov", "@%s,a", rname);
9445             }
9446           else
9447             emitcode ("mov", "@%s,%s", rname, l);
9448           break;
9449
9450         case FPOINTER:
9451           MOVA (l);
9452           emitcode ("movx", "@dptr,a");
9453           break;
9454
9455         case GPOINTER:
9456           MOVA (l);
9457           emitcode ("lcall", "__gptrput");
9458           break;
9459         }
9460       emitcode ("inc", "%s", rname);
9461     }
9462
9463   MOVA (l);
9464
9465   /* last last was not complete */
9466   if (rLen)
9467     {
9468       /* save the byte & read byte */
9469       switch (p_type)
9470         {
9471         case POINTER:
9472           emitcode ("mov", "b,a");
9473           emitcode ("mov", "a,@%s", rname);
9474           break;
9475
9476         case FPOINTER:
9477           emitcode ("mov", "b,a");
9478           emitcode ("movx", "a,@dptr");
9479           break;
9480
9481         case GPOINTER:
9482           emitcode ("push", "b");
9483           emitcode ("push", "acc");
9484           emitcode ("lcall", "__gptrget");
9485           emitcode ("pop", "b");
9486           break;
9487         }
9488
9489       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9490       emitcode ("orl", "a,b");
9491     }
9492
9493   if (p_type == GPOINTER)
9494     emitcode ("pop", "b");
9495
9496   switch (p_type)
9497     {
9498
9499     case POINTER:
9500       emitcode ("mov", "@%s,a", rname);
9501       break;
9502
9503     case FPOINTER:
9504       emitcode ("movx", "@dptr,a");
9505       break;
9506
9507     case GPOINTER:
9508       emitcode ("lcall", "__gptrput");
9509       break;
9510     }
9511 }
9512 /*-----------------------------------------------------------------*/
9513 /* genDataPointerSet - remat pointer to data space                 */
9514 /*-----------------------------------------------------------------*/
9515 static void
9516 genDataPointerSet (operand * right,
9517                    operand * result,
9518                    iCode * ic)
9519 {
9520   int size, offset = 0;
9521   char *l, buffer[256];
9522
9523   aopOp (right, ic, FALSE, FALSE);
9524
9525   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9526   size = AOP_SIZE (right);
9527   while (size--)
9528     {
9529       if (offset)
9530         sprintf (buffer, "(%s + %d)", l + 1, offset);
9531       else
9532         sprintf (buffer, "%s", l + 1);
9533       emitcode ("mov", "%s,%s", buffer,
9534                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9535     }
9536
9537   freeAsmop (right, NULL, ic, TRUE);
9538   freeAsmop (result, NULL, ic, TRUE);
9539 }
9540
9541 /*-----------------------------------------------------------------*/
9542 /* genNearPointerSet - emitcode for near pointer put                */
9543 /*-----------------------------------------------------------------*/
9544 static void
9545 genNearPointerSet (operand * right,
9546                    operand * result,
9547                    iCode * ic,
9548                    iCode * pi)
9549 {
9550   asmop *aop = NULL;
9551   regs *preg = NULL;
9552   char *rname, *l;
9553   sym_link *retype, *letype;
9554   sym_link *ptype = operandType (result);
9555
9556   retype = getSpec (operandType (right));
9557   letype = getSpec (ptype);
9558
9559   aopOp (result, ic, FALSE, FALSE);
9560
9561   /* if the result is rematerializable &
9562      in data space & not a bit variable */
9563   if (AOP_TYPE (result) == AOP_IMMD &&
9564       DCL_TYPE (ptype) == POINTER &&
9565       !IS_BITVAR (retype) &&
9566       !IS_BITVAR (letype))
9567     {
9568       genDataPointerSet (right, result, ic);
9569       return;
9570     }
9571
9572   /* if the value is already in a pointer register
9573      then don't need anything more */
9574   if (!AOP_INPREG (AOP (result)))
9575     {
9576       /* otherwise get a free pointer register */
9577       aop = newAsmop (0);
9578       preg = getFreePtr (ic, &aop, FALSE);
9579       emitcode ("mov", "%s,%s",
9580                 preg->name,
9581                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9582       rname = preg->name;
9583     }
9584   else
9585     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9586
9587   aopOp (right, ic, FALSE, FALSE);
9588
9589   /* if bitfield then unpack the bits */
9590   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9591     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9592   else
9593     {
9594       /* we have can just get the values */
9595       int size = AOP_SIZE (right);
9596       int offset = 0;
9597
9598       while (size--)
9599         {
9600           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9601           if (*l == '@')
9602             {
9603               MOVA (l);
9604               emitcode ("mov", "@%s,a", rname);
9605             }
9606           else
9607             emitcode ("mov", "@%s,%s", rname, l);
9608           if (size || pi)
9609             emitcode ("inc", "%s", rname);
9610           offset++;
9611         }
9612     }
9613
9614   /* now some housekeeping stuff */
9615   if (aop)
9616     {
9617       /* we had to allocate for this iCode */
9618       if (pi) aopPut (AOP (result),rname,0);
9619       freeAsmop (NULL, aop, ic, TRUE);
9620     }
9621   else
9622     {
9623       /* we did not allocate which means left
9624          already in a pointer register, then
9625          if size > 0 && this could be used again
9626          we have to point it back to where it
9627          belongs */
9628       if (AOP_SIZE (right) > 1 &&
9629           !OP_SYMBOL (result)->remat &&
9630           (OP_SYMBOL (result)->liveTo > ic->seq ||
9631            ic->depth) &&
9632           !pi)
9633         {
9634           int size = AOP_SIZE (right) - 1;
9635           while (size--)
9636             emitcode ("dec", "%s", rname);
9637         }
9638     }
9639
9640   /* done */
9641   if (pi) pi->generated = 1;
9642   freeAsmop (result, NULL, ic, TRUE);
9643   freeAsmop (right, NULL, ic, TRUE);
9644
9645
9646 }
9647
9648 /*-----------------------------------------------------------------*/
9649 /* genPagedPointerSet - emitcode for Paged pointer put             */
9650 /*-----------------------------------------------------------------*/
9651 static void
9652 genPagedPointerSet (operand * right,
9653                     operand * result,
9654                     iCode * ic,
9655                     iCode *pi)
9656 {
9657   asmop *aop = NULL;
9658   regs *preg = NULL;
9659   char *rname, *l;
9660   sym_link *retype, *letype;
9661
9662   retype = getSpec (operandType (right));
9663   letype = getSpec (operandType (result));
9664
9665   aopOp (result, ic, FALSE, FALSE);
9666
9667   /* if the value is already in a pointer register
9668      then don't need anything more */
9669   if (!AOP_INPREG (AOP (result)))
9670     {
9671       /* otherwise get a free pointer register */
9672       aop = newAsmop (0);
9673       preg = getFreePtr (ic, &aop, FALSE);
9674       emitcode ("mov", "%s,%s",
9675                 preg->name,
9676                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9677       rname = preg->name;
9678     }
9679   else
9680     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9681
9682   aopOp (right, ic, FALSE, FALSE);
9683
9684   /* if bitfield then unpack the bits */
9685   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9686     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9687   else
9688     {
9689       /* we have can just get the values */
9690       int size = AOP_SIZE (right);
9691       int offset = 0;
9692
9693       while (size--)
9694         {
9695           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9696
9697           MOVA (l);
9698           emitcode ("movx", "@%s,a", rname);
9699
9700           if (size || pi)
9701             emitcode ("inc", "%s", rname);
9702
9703           offset++;
9704         }
9705     }
9706
9707   /* now some housekeeping stuff */
9708   if (aop)
9709     {
9710       if (pi) aopPut (AOP (result),rname,0);
9711       /* we had to allocate for this iCode */
9712       freeAsmop (NULL, aop, ic, TRUE);
9713     }
9714   else
9715     {
9716       /* we did not allocate which means left
9717          already in a pointer register, then
9718          if size > 0 && this could be used again
9719          we have to point it back to where it
9720          belongs */
9721       if (AOP_SIZE (right) > 1 &&
9722           !OP_SYMBOL (result)->remat &&
9723           (OP_SYMBOL (result)->liveTo > ic->seq ||
9724            ic->depth) &&
9725           !pi)
9726         {
9727           int size = AOP_SIZE (right) - 1;
9728           while (size--)
9729             emitcode ("dec", "%s", rname);
9730         }
9731     }
9732
9733   /* done */
9734   if (pi) pi->generated = 1;
9735   freeAsmop (result, NULL, ic, TRUE);
9736   freeAsmop (right, NULL, ic, TRUE);
9737
9738
9739 }
9740
9741 /*-----------------------------------------------------------------*/
9742 /* genFarPointerSet - set value from far space                     */
9743 /*-----------------------------------------------------------------*/
9744 static void
9745 genFarPointerSet (operand * right,
9746                   operand * result, iCode * ic, iCode *pi)
9747 {
9748   int size, offset, dopi=1;
9749   sym_link *retype = getSpec (operandType (right));
9750   sym_link *letype = getSpec (operandType (result));
9751
9752   aopOp (result, ic, FALSE, FALSE);
9753
9754   /* if the operand is already in dptr
9755      then we do nothing else we move the value to dptr */
9756   if (AOP_TYPE (result) != AOP_STR)
9757     {
9758       /* if this is remateriazable */
9759       if (AOP_TYPE (result) == AOP_IMMD)
9760         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9761       else
9762         {
9763           /* we need to get it byte by byte */
9764           _startLazyDPSEvaluation ();
9765           if (AOP_TYPE (result) != AOP_DPTR)
9766             {
9767               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9768               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9769               if (options.model == MODEL_FLAT24)
9770                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9771             }
9772           else
9773             {
9774               /* We need to generate a load to DPTR indirect through DPTR. */
9775               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9776                 );
9777               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9778               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9779               if (options.model == MODEL_FLAT24)
9780                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9781               emitcode ("pop", "dph");
9782               emitcode ("pop", "dpl");
9783               dopi=0;
9784             }
9785           _endLazyDPSEvaluation ();
9786         }
9787     }
9788   /* so dptr know contains the address */
9789   aopOp (right, ic, FALSE, TRUE);
9790
9791   /* if bit then unpack */
9792   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9793     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9794   else
9795     {
9796       size = AOP_SIZE (right);
9797       offset = 0;
9798
9799       _startLazyDPSEvaluation ();
9800       while (size--)
9801         {
9802           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9803           MOVA (l);
9804
9805           genSetDPTR (0);
9806           _flushLazyDPS ();
9807
9808           emitcode ("movx", "@dptr,a");
9809           if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9810             emitcode ("inc", "dptr");
9811         }
9812       _endLazyDPSEvaluation ();
9813     }
9814
9815   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9816       aopPut (AOP(result),"dpl",0);
9817       aopPut (AOP(result),"dph",1);
9818       if (options.model == MODEL_FLAT24)
9819           aopPut (AOP(result),"dpx",2);
9820       pi->generated=1;
9821   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9822              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9823       
9824       size = AOP_SIZE (right) - 1;
9825       while (size--) emitcode ("lcall","__decdptr");
9826   }
9827   freeAsmop (result, NULL, ic, TRUE);
9828   freeAsmop (right, NULL, ic, TRUE);
9829 }
9830
9831 /*-----------------------------------------------------------------*/
9832 /* genGenPointerSet - set value from generic pointer space         */
9833 /*-----------------------------------------------------------------*/
9834 static void
9835 genGenPointerSet (operand * right,
9836                   operand * result, iCode * ic, iCode *pi)
9837 {
9838   int size, offset;
9839   sym_link *retype = getSpec (operandType (right));
9840   sym_link *letype = getSpec (operandType (result));
9841
9842   aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9843
9844   /* if the operand is already in dptr
9845      then we do nothing else we move the value to dptr */
9846   if (AOP_TYPE (result) != AOP_STR)
9847     {
9848       _startLazyDPSEvaluation ();
9849       /* if this is remateriazable */
9850       if (AOP_TYPE (result) == AOP_IMMD)
9851         {
9852           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9853           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
9854                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9855           else
9856                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9857         }
9858       else
9859         {                       /* we need to get it byte by byte */
9860           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9861           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9862           if (options.model == MODEL_FLAT24) {
9863             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9864             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9865           } else {
9866             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9867           }
9868         }
9869       _endLazyDPSEvaluation ();
9870     }
9871   /* so dptr know contains the address */
9872   aopOp (right, ic, FALSE, TRUE);
9873
9874   /* if bit then unpack */
9875   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9876     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9877   else
9878     {
9879       size = AOP_SIZE (right);
9880       offset = 0;
9881
9882       _startLazyDPSEvaluation ();
9883       while (size--)
9884         {
9885           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9886           MOVA (l);
9887
9888           genSetDPTR (0);
9889           _flushLazyDPS ();
9890
9891           emitcode ("lcall", "__gptrput");
9892           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9893             emitcode ("inc", "dptr");
9894         }
9895       _endLazyDPSEvaluation ();
9896     }
9897
9898   if (pi && AOP_TYPE (result) != AOP_IMMD) {
9899       aopPut (AOP(result),"dpl",0);
9900       aopPut (AOP(result),"dph",1);
9901       if (options.model == MODEL_FLAT24) {
9902           aopPut (AOP(result),"dpx",2);
9903           aopPut (AOP(result),"b",3);
9904       } else {
9905           aopPut (AOP(result),"b",2);
9906       }
9907       pi->generated=1;
9908   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9909              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9910       
9911       size = AOP_SIZE (right) - 1;
9912       while (size--) emitcode ("lcall","__decdptr");
9913   }
9914   freeAsmop (result, NULL, ic, TRUE);
9915   freeAsmop (right, NULL, ic, TRUE);
9916 }
9917
9918 /*-----------------------------------------------------------------*/
9919 /* genPointerSet - stores the value into a pointer location        */
9920 /*-----------------------------------------------------------------*/
9921 static void
9922 genPointerSet (iCode * ic, iCode *pi)
9923 {
9924   operand *right, *result;
9925   sym_link *type, *etype;
9926   int p_type;
9927
9928   D (emitcode (";", "genPointerSet ");
9929     );
9930
9931   right = IC_RIGHT (ic);
9932   result = IC_RESULT (ic);
9933
9934   /* depending on the type of pointer we need to
9935      move it to the correct pointer register */
9936   type = operandType (result);
9937   etype = getSpec (type);
9938   /* if left is of type of pointer then it is simple */
9939   if (IS_PTR (type) && !IS_FUNC (type->next))
9940     {
9941       p_type = DCL_TYPE (type);
9942     }
9943   else
9944     {
9945       /* we have to go by the storage class */
9946       p_type = PTR_TYPE (SPEC_OCLS (etype));
9947     }
9948   /* special case when cast remat */
9949   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9950       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9951           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9952           type =   type = operandType (result);
9953           p_type = DCL_TYPE (type);
9954   }
9955
9956   /* now that we have the pointer type we assign
9957      the pointer values */
9958   switch (p_type)
9959     {
9960
9961     case POINTER:
9962     case IPOINTER:
9963       genNearPointerSet (right, result, ic, pi);
9964       break;
9965
9966     case PPOINTER:
9967       genPagedPointerSet (right, result, ic, pi);
9968       break;
9969
9970     case FPOINTER:
9971       genFarPointerSet (right, result, ic, pi);
9972       break;
9973
9974     case GPOINTER:
9975       genGenPointerSet (right, result, ic, pi);
9976       break;
9977     }
9978
9979 }
9980
9981 /*-----------------------------------------------------------------*/
9982 /* genIfx - generate code for Ifx statement                        */
9983 /*-----------------------------------------------------------------*/
9984 static void
9985 genIfx (iCode * ic, iCode * popIc)
9986 {
9987   operand *cond = IC_COND (ic);
9988   int isbit = 0;
9989
9990   D (emitcode (";", "genIfx "););
9991
9992   aopOp (cond, ic, FALSE, FALSE);
9993
9994   /* get the value into acc */
9995   if (AOP_TYPE (cond) != AOP_CRY)
9996     toBoolean (cond);
9997   else
9998     isbit = 1;
9999   /* the result is now in the accumulator */
10000   freeAsmop (cond, NULL, ic, TRUE);
10001
10002   /* if there was something to be popped then do it */
10003   if (popIc)
10004     genIpop (popIc);
10005
10006   /* if the condition is  a bit variable */
10007   if (isbit && IS_ITEMP (cond) &&
10008       SPIL_LOC (cond))
10009     genIfxJump (ic, SPIL_LOC (cond)->rname);
10010   else if (isbit && !IS_ITEMP (cond))
10011     genIfxJump (ic, OP_SYMBOL (cond)->rname);
10012   else
10013     genIfxJump (ic, "a");
10014
10015   ic->generated = 1;
10016 }
10017
10018 /*-----------------------------------------------------------------*/
10019 /* genAddrOf - generates code for address of                       */
10020 /*-----------------------------------------------------------------*/
10021 static void
10022 genAddrOf (iCode * ic)
10023 {
10024   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10025   int size, offset;
10026
10027   D (emitcode (";", "genAddrOf ");
10028     );
10029
10030   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10031
10032   /* if the operand is on the stack then we
10033      need to get the stack offset of this
10034      variable */
10035   if (sym->onStack) {
10036       
10037       /* if 10 bit stack */
10038       if (options.stack10bit) {
10039           char buff[10];
10040           tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10041           /* if it has an offset then we need to compute it */
10042           emitcode ("subb", "a,#!constbyte",
10043                     -((sym->stack < 0) ?
10044                       ((short) (sym->stack - _G.nRegsSaved)) :
10045                       ((short) sym->stack)) & 0xff);
10046           emitcode ("mov","b,a");
10047           emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
10048                                          ((short) (sym->stack - _G.nRegsSaved)) :
10049                                          ((short) sym->stack)) >> 8) & 0xff);
10050           if (sym->stack) {
10051               emitcode ("mov", "a,_bpx");
10052               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10053                                              ((char) (sym->stack - _G.nRegsSaved)) :
10054                                              ((char) sym->stack )) & 0xff);
10055               emitcode ("mov", "b,a");
10056               emitcode ("mov", "a,_bpx+1");
10057               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
10058                                               ((short) (sym->stack - _G.nRegsSaved)) :
10059                                               ((short) sym->stack )) >> 8) & 0xff);
10060               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10061               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10062               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10063           } else {
10064               /* we can just move _bp */
10065               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10066               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10067               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10068           }       
10069       } else {
10070           /* if it has an offset then we need to compute it */
10071           if (sym->stack) {
10072               emitcode ("mov", "a,_bp");
10073               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10074               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10075           } else {
10076               /* we can just move _bp */
10077               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10078           }
10079           /* fill the result with zero */
10080           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10081           
10082           
10083           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10084               fprintf (stderr,
10085                        "*** warning: pointer to stack var truncated.\n");
10086           }
10087
10088           offset = 1;
10089           while (size--) {
10090               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10091           }      
10092       }
10093       goto release;
10094   }
10095
10096   /* object not on stack then we need the name */
10097   size = AOP_SIZE (IC_RESULT (ic));
10098   offset = 0;
10099
10100   while (size--)
10101     {
10102       char s[SDCC_NAME_MAX];
10103       if (offset) {
10104           switch (offset) {
10105           case 1:
10106               tsprintf(s,"!his",sym->rname);
10107               break;
10108           case 2:
10109               tsprintf(s,"!hihis",sym->rname);
10110               break;
10111           case 3:
10112               tsprintf(s,"!hihihis",sym->rname);
10113               break;
10114           default: /* should not need this (just in case) */
10115               sprintf (s, "#(%s >> %d)",
10116                        sym->rname,
10117                        offset * 8);
10118           }
10119       } else
10120           sprintf (s, "#%s", sym->rname);
10121       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10122     }
10123
10124 release:
10125   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10126
10127 }
10128
10129 /*-----------------------------------------------------------------*/
10130 /* genArrayInit - generates code for address of                       */
10131 /*-----------------------------------------------------------------*/
10132 static void
10133 genArrayInit (iCode * ic)
10134 {
10135     literalList *iLoop;
10136     int         ix, count;
10137     int         elementSize = 0, eIndex;
10138     unsigned    val, lastVal;
10139     sym_link    *type;
10140     operand     *left=IC_LEFT(ic);
10141     
10142     D (emitcode (";", "genArrayInit "););
10143
10144     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10145     
10146     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10147     {
10148         // Load immediate value into DPTR.
10149         emitcode("mov", "dptr, %s",
10150              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10151     }
10152     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10153     {
10154 #if 0
10155       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10156               "Unexpected operand to genArrayInit.\n");
10157       exit(1);
10158 #else
10159       // a regression because of SDCCcse.c:1.52
10160       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10161       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10162       if (options.model == MODEL_FLAT24)
10163         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10164 #endif
10165     }
10166     
10167     type = operandType(IC_LEFT(ic));
10168     
10169     if (type && type->next)
10170     {
10171         elementSize = getSize(type->next);
10172     }
10173     else
10174     {
10175         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10176                                 "can't determine element size in genArrayInit.\n");
10177         exit(1);
10178     }
10179     
10180     iLoop = IC_ARRAYILIST(ic);
10181     lastVal = 0xffff;
10182     
10183     while (iLoop)
10184     {
10185         bool firstpass = TRUE;
10186         
10187         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10188                  iLoop->count, (int)iLoop->literalValue, elementSize);
10189         
10190         ix = iLoop->count;
10191         
10192         while (ix)
10193         {
10194             symbol *tlbl = NULL;
10195             
10196             count = ix > 256 ? 256 : ix;
10197             
10198             if (count > 1)
10199             {
10200                 tlbl = newiTempLabel (NULL);
10201                 if (firstpass || (count & 0xff))
10202                 {
10203                     emitcode("mov", "b, #!constbyte", count & 0xff);
10204                 }
10205                 
10206                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10207             }
10208             
10209             firstpass = FALSE;
10210                 
10211             for (eIndex = 0; eIndex < elementSize; eIndex++)
10212             {
10213                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10214                 if (val != lastVal)
10215                 {
10216                     emitcode("mov", "a, #!constbyte", val);
10217                     lastVal = val;
10218                 }
10219                 
10220                 emitcode("movx", "@dptr, a");
10221                 emitcode("inc", "dptr");
10222             }
10223             
10224             if (count > 1)
10225             {
10226                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10227             }
10228             
10229             ix -= count;
10230         }
10231         
10232         iLoop = iLoop->next;
10233     }
10234     
10235     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10236 }
10237
10238 /*-----------------------------------------------------------------*/
10239 /* genFarFarAssign - assignment when both are in far space         */
10240 /*-----------------------------------------------------------------*/
10241 static void
10242 genFarFarAssign (operand * result, operand * right, iCode * ic)
10243 {
10244   int size = AOP_SIZE (right);
10245   int offset = 0;
10246   symbol *rSym = NULL;
10247
10248   if (size == 1)
10249   {
10250       /* quick & easy case. */
10251       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10252       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10253       freeAsmop (right, NULL, ic, FALSE);
10254       /* now assign DPTR to result */
10255       _G.accInUse++;
10256       aopOp(result, ic, FALSE, FALSE);
10257       _G.accInUse--;
10258       aopPut(AOP(result), "a", 0);
10259       freeAsmop(result, NULL, ic, FALSE);
10260       return;
10261   }
10262   
10263   /* See if we've got an underlying symbol to abuse. */
10264   if (IS_SYMOP(result) && OP_SYMBOL(result))
10265   {
10266       if (IS_TRUE_SYMOP(result))
10267       {
10268           rSym = OP_SYMBOL(result);
10269       }
10270       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10271       {
10272           rSym = OP_SYMBOL(result)->usl.spillLoc;
10273       }
10274   }
10275              
10276   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10277   {
10278       /* We can use the '390 auto-toggle feature to good effect here. */
10279       
10280       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10281       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10282       emitcode ("mov", "dptr,#%s", rSym->rname); 
10283       /* DP2 = result, DP1 = right, DP1 is current. */
10284       while (size)
10285       {
10286           emitcode("movx", "a,@dptr");
10287           emitcode("movx", "@dptr,a");
10288           if (--size)
10289           {
10290                emitcode("inc", "dptr");
10291                emitcode("inc", "dptr");
10292           }
10293       }
10294       emitcode("mov", "dps,#0");
10295       freeAsmop (right, NULL, ic, FALSE);
10296 #if 0
10297 some alternative code for processors without auto-toggle
10298 no time to test now, so later well put in...kpb
10299         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10300         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10301         emitcode ("mov", "dptr,#%s", rSym->rname); 
10302         /* DP2 = result, DP1 = right, DP1 is current. */
10303         while (size)
10304         {
10305           --size;
10306           emitcode("movx", "a,@dptr");
10307           if (size)
10308             emitcode("inc", "dptr");
10309           emitcode("inc", "dps");
10310           emitcode("movx", "@dptr,a");
10311           if (size)
10312             emitcode("inc", "dptr");
10313           emitcode("inc", "dps");
10314         }
10315         emitcode("mov", "dps,#0");
10316         freeAsmop (right, NULL, ic, FALSE);
10317 #endif
10318   }
10319   else
10320   {
10321       D (emitcode (";", "genFarFarAssign"););
10322       aopOp (result, ic, TRUE, TRUE);
10323
10324       _startLazyDPSEvaluation ();
10325       
10326       while (size--)
10327         {
10328           aopPut (AOP (result),
10329                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10330           offset++;
10331         }
10332       _endLazyDPSEvaluation ();
10333       freeAsmop (result, NULL, ic, FALSE);
10334       freeAsmop (right, NULL, ic, FALSE);
10335   }
10336 }
10337
10338 /*-----------------------------------------------------------------*/
10339 /* genAssign - generate code for assignment                        */
10340 /*-----------------------------------------------------------------*/
10341 static void
10342 genAssign (iCode * ic)
10343 {
10344   operand *result, *right;
10345   int size, offset;
10346   unsigned long lit = 0L;
10347
10348   D (emitcode (";", "genAssign ");
10349     );
10350
10351   result = IC_RESULT (ic);
10352   right = IC_RIGHT (ic);
10353
10354   /* if they are the same */
10355   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10356     return;
10357
10358   aopOp (right, ic, FALSE, FALSE);
10359
10360   emitcode (";", "genAssign: resultIsFar = %s",
10361             isOperandInFarSpace (result) ?
10362             "TRUE" : "FALSE");
10363
10364   /* special case both in far space */
10365   if ((AOP_TYPE (right) == AOP_DPTR ||
10366        AOP_TYPE (right) == AOP_DPTR2) &&
10367   /* IS_TRUE_SYMOP(result)       && */
10368       isOperandInFarSpace (result))
10369     {
10370       genFarFarAssign (result, right, ic);
10371       return;
10372     }
10373
10374   aopOp (result, ic, TRUE, FALSE);
10375
10376   /* if they are the same registers */
10377   if (sameRegs (AOP (right), AOP (result)))
10378     goto release;
10379
10380   /* if the result is a bit */
10381   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10382     {
10383       /* if the right size is a literal then
10384          we know what the value is */
10385       if (AOP_TYPE (right) == AOP_LIT)
10386         {
10387           if (((int) operandLitValue (right)))
10388             aopPut (AOP (result), one, 0);
10389           else
10390             aopPut (AOP (result), zero, 0);
10391           goto release;
10392         }
10393
10394       /* the right is also a bit variable */
10395       if (AOP_TYPE (right) == AOP_CRY)
10396         {
10397           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10398           aopPut (AOP (result), "c", 0);
10399           goto release;
10400         }
10401
10402       /* we need to or */
10403       toBoolean (right);
10404       aopPut (AOP (result), "a", 0);
10405       goto release;
10406     }
10407
10408   /* bit variables done */
10409   /* general case */
10410   size = AOP_SIZE (result);
10411   offset = 0;
10412   if (AOP_TYPE (right) == AOP_LIT)
10413     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10414
10415   if ((size > 1) &&
10416       (AOP_TYPE (result) != AOP_REG) &&
10417       (AOP_TYPE (right) == AOP_LIT) &&
10418       !IS_FLOAT (operandType (right)))
10419     {
10420       _startLazyDPSEvaluation ();
10421       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10422         {
10423           aopPut (AOP (result),
10424                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10425                   offset);
10426           offset++;
10427           size--;
10428         }
10429       /* And now fill the rest with zeros. */
10430       if (size)
10431         {
10432           emitcode ("clr", "a");
10433         }
10434       while (size--)
10435         {
10436           aopPut (AOP (result), "a", offset++);
10437         }
10438       _endLazyDPSEvaluation ();
10439     }
10440   else
10441     {
10442       _startLazyDPSEvaluation ();
10443       while (size--)
10444         {
10445           aopPut (AOP (result),
10446                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10447                   offset);
10448           offset++;
10449         }
10450       _endLazyDPSEvaluation ();
10451     }
10452
10453 release:
10454   freeAsmop (right, NULL, ic, FALSE);
10455   freeAsmop (result, NULL, ic, TRUE);
10456 }
10457
10458 /*-----------------------------------------------------------------*/
10459 /* genJumpTab - generates code for jump table                      */
10460 /*-----------------------------------------------------------------*/
10461 static void
10462 genJumpTab (iCode * ic)
10463 {
10464   symbol *jtab;
10465   char *l;
10466
10467   D (emitcode (";", "genJumpTab ");
10468     );
10469
10470   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10471   /* get the condition into accumulator */
10472   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10473   MOVA (l);
10474   /* multiply by four! */
10475   emitcode ("add", "a,acc");
10476   emitcode ("add", "a,acc");
10477   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10478
10479   jtab = newiTempLabel (NULL);
10480   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10481   emitcode ("jmp", "@a+dptr");
10482   emitcode ("", "!tlabeldef", jtab->key + 100);
10483   /* now generate the jump labels */
10484   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10485        jtab = setNextItem (IC_JTLABELS (ic)))
10486     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10487
10488 }
10489
10490 /*-----------------------------------------------------------------*/
10491 /* genCast - gen code for casting                                  */
10492 /*-----------------------------------------------------------------*/
10493 static void
10494 genCast (iCode * ic)
10495 {
10496   operand *result = IC_RESULT (ic);
10497   sym_link *ctype = operandType (IC_LEFT (ic));
10498   sym_link *rtype = operandType (IC_RIGHT (ic));
10499   operand *right = IC_RIGHT (ic);
10500   int size, offset;
10501
10502   D (emitcode (";", "genCast ");
10503     );
10504
10505   /* if they are equivalent then do nothing */
10506   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10507     return;
10508
10509   aopOp (right, ic, FALSE, FALSE);
10510   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10511
10512   /* if the result is a bit */
10513   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10514   if (IS_BITVAR(OP_SYMBOL(result)->type))
10515     {
10516       /* if the right size is a literal then
10517          we know what the value is */
10518       if (AOP_TYPE (right) == AOP_LIT)
10519         {
10520           if (((int) operandLitValue (right)))
10521             aopPut (AOP (result), one, 0);
10522           else
10523             aopPut (AOP (result), zero, 0);
10524
10525           goto release;
10526         }
10527
10528       /* the right is also a bit variable */
10529       if (AOP_TYPE (right) == AOP_CRY)
10530         {
10531           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10532           aopPut (AOP (result), "c", 0);
10533           goto release;
10534         }
10535
10536       /* we need to or */
10537       toBoolean (right);
10538       aopPut (AOP (result), "a", 0);
10539       goto release;
10540     }
10541
10542   /* if they are the same size : or less */
10543   if (AOP_SIZE (result) <= AOP_SIZE (right))
10544     {
10545
10546       /* if they are in the same place */
10547       if (sameRegs (AOP (right), AOP (result)))
10548         goto release;
10549
10550       /* if they in different places then copy */
10551       size = AOP_SIZE (result);
10552       offset = 0;
10553       _startLazyDPSEvaluation ();
10554       while (size--)
10555         {
10556           aopPut (AOP (result),
10557                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10558                   offset);
10559           offset++;
10560         }
10561       _endLazyDPSEvaluation ();
10562       goto release;
10563     }
10564
10565
10566   /* if the result is of type pointer */
10567   if (IS_PTR (ctype))
10568     {
10569
10570       int p_type;
10571       sym_link *type = operandType (right);
10572
10573       /* pointer to generic pointer */
10574       if (IS_GENPTR (ctype))
10575         {
10576           char *l = zero;
10577
10578           if (IS_PTR (type))
10579             {
10580               p_type = DCL_TYPE (type);
10581             }
10582           else
10583             {
10584 #if OLD_CAST_BEHAVIOR
10585               /* KV: we are converting a non-pointer type to
10586                * a generic pointer. This (ifdef'd out) code
10587                * says that the resulting generic pointer
10588                * should have the same class as the storage
10589                * location of the non-pointer variable.
10590                *
10591                * For example, converting an int (which happens
10592                * to be stored in DATA space) to a pointer results
10593                * in a DATA generic pointer; if the original int
10594                * in XDATA space, so will be the resulting pointer.
10595                *
10596                * I don't like that behavior, and thus this change:
10597                * all such conversions will be forced to XDATA and
10598                * throw a warning. If you want some non-XDATA
10599                * type, or you want to suppress the warning, you
10600                * must go through an intermediate cast, like so:
10601                *
10602                * char _generic *gp = (char _xdata *)(intVar);
10603                */
10604               sym_link *etype = getSpec (type);
10605
10606               /* we have to go by the storage class */
10607               if (SPEC_OCLS (etype) != generic)
10608                 {
10609                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10610                 }
10611               else
10612 #endif
10613                 {
10614                   /* Converting unknown class (i.e. register variable)
10615                    * to generic pointer. This is not good, but
10616                    * we'll make a guess (and throw a warning).
10617                    */
10618                   p_type = FPOINTER;
10619                   werror (W_INT_TO_GEN_PTR_CAST);
10620                 }
10621             }
10622
10623           /* the first two bytes are known */
10624           size = GPTRSIZE - 1;
10625           offset = 0;
10626           _startLazyDPSEvaluation ();
10627           while (size--)
10628             {
10629               aopPut (AOP (result),
10630                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10631                       offset);
10632               offset++;
10633             }
10634           _endLazyDPSEvaluation ();
10635
10636           /* the last byte depending on type */
10637           switch (p_type)
10638             {
10639             case IPOINTER:
10640             case POINTER:
10641               l = zero;
10642               break;
10643             case FPOINTER:
10644               l = one;
10645               break;
10646             case CPOINTER:
10647               l = "#0x02";
10648               break;
10649             case PPOINTER:
10650               l = "#0x03";
10651               break;
10652
10653             default:
10654               /* this should never happen */
10655               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10656                       "got unknown pointer type");
10657               exit (1);
10658             }
10659           aopPut (AOP (result), l, GPTRSIZE - 1);
10660           goto release;
10661         }
10662
10663       /* just copy the pointers */
10664       size = AOP_SIZE (result);
10665       offset = 0;
10666       _startLazyDPSEvaluation ();
10667       while (size--)
10668         {
10669           aopPut (AOP (result),
10670                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10671                   offset);
10672           offset++;
10673         }
10674       _endLazyDPSEvaluation ();
10675       goto release;
10676     }
10677
10678   /* so we now know that the size of destination is greater
10679      than the size of the source */
10680   /* we move to result for the size of source */
10681   size = AOP_SIZE (right);
10682   offset = 0;
10683   _startLazyDPSEvaluation ();
10684   while (size--)
10685     {
10686       aopPut (AOP (result),
10687               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10688               offset);
10689       offset++;
10690     }
10691   _endLazyDPSEvaluation ();
10692
10693   /* now depending on the sign of the source && destination */
10694   size = AOP_SIZE (result) - AOP_SIZE (right);
10695   /* if unsigned or not an integral type */
10696   /* also, if the source is a bit, we don't need to sign extend, because
10697    * it can't possibly have set the sign bit.
10698    */
10699   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10700     {
10701       while (size--)
10702         {
10703           aopPut (AOP (result), zero, offset++);
10704         }
10705     }
10706   else
10707     {
10708       /* we need to extend the sign :{ */
10709       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10710                         FALSE, FALSE, TRUE);
10711       MOVA (l);
10712       emitcode ("rlc", "a");
10713       emitcode ("subb", "a,acc");
10714       while (size--)
10715         aopPut (AOP (result), "a", offset++);
10716     }
10717
10718   /* we are done hurray !!!! */
10719
10720 release:
10721   freeAsmop (right, NULL, ic, TRUE);
10722   freeAsmop (result, NULL, ic, TRUE);
10723
10724 }
10725
10726 /*-----------------------------------------------------------------*/
10727 /* genDjnz - generate decrement & jump if not zero instrucion      */
10728 /*-----------------------------------------------------------------*/
10729 static int
10730 genDjnz (iCode * ic, iCode * ifx)
10731 {
10732   symbol *lbl, *lbl1;
10733   if (!ifx)
10734     return 0;
10735
10736   /* if the if condition has a false label
10737      then we cannot save */
10738   if (IC_FALSE (ifx))
10739     return 0;
10740
10741   /* if the minus is not of the form
10742      a = a - 1 */
10743   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10744       !IS_OP_LITERAL (IC_RIGHT (ic)))
10745     return 0;
10746
10747   if (operandLitValue (IC_RIGHT (ic)) != 1)
10748     return 0;
10749
10750   /* if the size of this greater than one then no
10751      saving */
10752   if (getSize (operandType (IC_RESULT (ic))) > 1)
10753     return 0;
10754
10755   /* otherwise we can save BIG */
10756   D(emitcode(";", "genDjnz"););
10757
10758   lbl = newiTempLabel (NULL);
10759   lbl1 = newiTempLabel (NULL);
10760
10761   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10762
10763   if (AOP_NEEDSACC(IC_RESULT(ic)))
10764   {
10765       /* If the result is accessed indirectly via
10766        * the accumulator, we must explicitly write
10767        * it back after the decrement.
10768        */
10769       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10770       
10771       if (strcmp(rByte, "a"))
10772       {
10773            /* Something is hopelessly wrong */
10774            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10775                    __FILE__, __LINE__);
10776            /* We can just give up; the generated code will be inefficient,
10777             * but what the hey.
10778             */
10779            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10780            return 0;
10781       }
10782       emitcode ("dec", "%s", rByte);
10783       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10784       emitcode ("jnz", "!tlabel", lbl->key + 100);
10785   }
10786   else if (IS_AOP_PREG (IC_RESULT (ic)))
10787     {
10788       emitcode ("dec", "%s",
10789                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10790       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10791       emitcode ("jnz", "!tlabel", lbl->key + 100);
10792     }
10793   else
10794     {
10795       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10796                 lbl->key + 100);
10797     }
10798   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10799   emitcode ("", "!tlabeldef", lbl->key + 100);
10800   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10801   emitcode ("", "!tlabeldef", lbl1->key + 100);
10802
10803   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10804   ifx->generated = 1;
10805   return 1;
10806 }
10807
10808 /*-----------------------------------------------------------------*/
10809 /* genReceive - generate code for a receive iCode                  */
10810 /*-----------------------------------------------------------------*/
10811 static void
10812 genReceive (iCode * ic)
10813 {
10814
10815   D (emitcode (";", "genReceive ");
10816     );
10817
10818   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10819       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10820        IS_TRUE_SYMOP (IC_RESULT (ic))))
10821     {
10822       int size = getSize (operandType (IC_RESULT (ic)));
10823       int offset = fReturnSizeDS390 - size;
10824       while (size--)
10825         {
10826           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10827                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10828           offset++;
10829         }
10830       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10831       size = AOP_SIZE (IC_RESULT (ic));
10832       offset = 0;
10833       while (size--)
10834         {
10835           emitcode ("pop", "acc");
10836           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10837         }
10838
10839     }
10840   else
10841     {
10842       _G.accInUse++;
10843       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10844       _G.accInUse--;
10845       assignResultValue (IC_RESULT (ic));
10846     }
10847
10848   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10849 }
10850
10851 /*-----------------------------------------------------------------*/
10852 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
10853 /*-----------------------------------------------------------------*/
10854 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10855 {
10856     operand *from , *to , *count;
10857     symbol *lbl;
10858     bitVect *rsave;
10859     int i;
10860
10861     /* we know it has to be 3 parameters */
10862     assert (nparms == 3);
10863     
10864     rsave = newBitVect(16);
10865     /* save DPTR if it needs to be saved */
10866     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10867             if (bitVectBitValue(ic->rMask,i))
10868                     rsave = bitVectSetBit(rsave,i);
10869     }
10870     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10871                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
10872     savermask(rsave);
10873     
10874     to = parms[0];
10875     from = parms[1];
10876     count = parms[2];
10877
10878     aopOp (from, ic->next, FALSE, FALSE);
10879
10880     /* get from into DPTR1 */
10881     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10882     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10883     if (options.model == MODEL_FLAT24) {
10884         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10885     }
10886
10887     freeAsmop (from, NULL, ic, FALSE);
10888     aopOp (to, ic, FALSE, FALSE);
10889     /* get "to" into DPTR */
10890     /* if the operand is already in dptr
10891        then we do nothing else we move the value to dptr */
10892     if (AOP_TYPE (to) != AOP_STR) {
10893         /* if already in DPTR then we need to push */
10894         if (AOP_TYPE(to) == AOP_DPTR) {
10895             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10896             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10897             if (options.model == MODEL_FLAT24)
10898                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10899             emitcode ("pop", "dph");
10900             emitcode ("pop", "dpl");        
10901         } else {
10902             _startLazyDPSEvaluation ();
10903             /* if this is remateriazable */
10904             if (AOP_TYPE (to) == AOP_IMMD) {
10905                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10906             } else {                    /* we need to get it byte by byte */
10907                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10908                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10909                 if (options.model == MODEL_FLAT24) {
10910                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10911                 }
10912             }
10913             _endLazyDPSEvaluation ();
10914         }
10915     }
10916     freeAsmop (to, NULL, ic, FALSE);
10917
10918     aopOp (count, ic->next->next, FALSE,FALSE);
10919     lbl =newiTempLabel(NULL);
10920
10921     /* now for the actual copy */
10922     if (AOP_TYPE(count) == AOP_LIT && 
10923         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10924         emitcode (";","OH  JOY auto increment with djnz (very fast)");
10925         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
10926         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10927         emitcode ("","!tlabeldef",lbl->key+100);
10928         if (fromc) {
10929             emitcode ("clr","a");
10930             emitcode ("movc", "a,@a+dptr");
10931         } else 
10932             emitcode ("movx", "a,@dptr");
10933         emitcode ("movx", "@dptr,a");
10934         emitcode ("inc", "dptr");
10935         emitcode ("inc", "dptr");
10936         emitcode ("djnz","b,!tlabel",lbl->key+100);
10937     } else {
10938         symbol *lbl1 = newiTempLabel(NULL);
10939         
10940         emitcode (";"," Auto increment but no djnz");
10941         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10942         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10943         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
10944         emitcode ("","!tlabeldef",lbl->key+100);
10945         if (fromc) {
10946             emitcode ("clr","a");
10947             emitcode ("movc", "a,@a+dptr");
10948         } else 
10949             emitcode ("movx", "a,@dptr");
10950         emitcode ("movx", "@dptr,a");
10951         emitcode ("inc", "dptr");
10952         emitcode ("inc", "dptr");
10953         emitcode ("mov","a,b");
10954         emitcode ("orl","a,_ap");
10955         emitcode ("jz","!tlabel",lbl1->key+100);
10956         emitcode ("mov","a,_ap");
10957         emitcode ("add","a,#!constbyte",0xFF);
10958         emitcode ("mov","_ap,a");
10959         emitcode ("mov","a,b");
10960         emitcode ("addc","a,#!constbyte",0xFF);
10961         emitcode ("mov","b,a");
10962         emitcode ("sjmp","!tlabel",lbl->key+100);
10963         emitcode ("","!tlabeldef",lbl1->key+100);
10964     }
10965     emitcode ("mov", "dps,#0"); 
10966     freeAsmop (count, NULL, ic, FALSE);
10967     unsavermask(rsave);
10968
10969 }
10970
10971 /*-----------------------------------------------------------------*/
10972 /* genMemsetX - gencode for memSetX data                           */
10973 /*-----------------------------------------------------------------*/
10974 static void genMemsetX(iCode *ic, int nparms, operand **parms)
10975 {
10976     operand *to , *val , *count;
10977     symbol *lbl;
10978     char *l;
10979     int i;
10980     bitVect *rsave = NULL;
10981
10982     /* we know it has to be 3 parameters */
10983     assert (nparms == 3);
10984     
10985     to = parms[0];
10986     val = parms[1];
10987     count = parms[2];
10988         
10989     /* save DPTR if it needs to be saved */
10990     rsave = newBitVect(16);
10991     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10992             if (bitVectBitValue(ic->rMask,i))
10993                     rsave = bitVectSetBit(rsave,i);
10994     }
10995     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10996                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
10997     savermask(rsave);
10998
10999     aopOp (to, ic, FALSE, FALSE);
11000     /* get "to" into DPTR */
11001     /* if the operand is already in dptr
11002        then we do nothing else we move the value to dptr */
11003     if (AOP_TYPE (to) != AOP_STR) {
11004         /* if already in DPTR then we need to push */
11005         if (AOP_TYPE(to) == AOP_DPTR) {
11006             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11007             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11008             if (options.model == MODEL_FLAT24)
11009                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11010             emitcode ("pop", "dph");
11011             emitcode ("pop", "dpl");        
11012         } else {
11013             _startLazyDPSEvaluation ();
11014             /* if this is remateriazable */
11015             if (AOP_TYPE (to) == AOP_IMMD) {
11016                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11017             } else {                    /* we need to get it byte by byte */
11018                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11019                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11020                 if (options.model == MODEL_FLAT24) {
11021                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11022                 }
11023             }
11024             _endLazyDPSEvaluation ();
11025         }
11026     }
11027     freeAsmop (to, NULL, ic, FALSE);
11028
11029     aopOp (val, ic->next->next, FALSE,FALSE);
11030     aopOp (count, ic->next->next, FALSE,FALSE);    
11031     lbl =newiTempLabel(NULL);
11032     /* now for the actual copy */
11033     if (AOP_TYPE(count) == AOP_LIT && 
11034         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11035         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11036         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11037         MOVA(l);
11038         emitcode ("","!tlabeldef",lbl->key+100);
11039         emitcode ("movx", "@dptr,a");
11040         emitcode ("inc", "dptr");
11041         emitcode ("djnz","b,!tlabel",lbl->key+100);
11042     } else {
11043         symbol *lbl1 = newiTempLabel(NULL);
11044         
11045         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11046         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11047         emitcode ("","!tlabeldef",lbl->key+100);
11048         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11049         MOVA(l);
11050         emitcode ("movx", "a,@dptr");
11051         emitcode ("inc", "dptr");
11052         emitcode ("mov","a,b");
11053         emitcode ("orl","a,_ap");
11054         emitcode ("jz","!tlabel",lbl1->key+100);
11055         emitcode ("mov","a,_ap");
11056         emitcode ("add","a,#!constbyte",0xFF);
11057         emitcode ("mov","_ap,a");
11058         emitcode ("mov","a,b");
11059         emitcode ("addc","a,#!constbyte",0xFF);
11060         emitcode ("mov","b,a");
11061         emitcode ("sjmp","!tlabel",lbl->key+100);
11062         emitcode ("","!tlabeldef",lbl1->key+100);
11063     }
11064     freeAsmop (count, NULL, ic, FALSE);
11065     unsavermask(rsave);
11066 }
11067
11068 /*-----------------------------------------------------------------*/
11069 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11070 /*-----------------------------------------------------------------*/
11071 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11072 {
11073         bitVect *rsave ;
11074         operand *pnum, *result;
11075         int i;
11076     
11077         assert (nparms==1);
11078         /* save registers that need to be saved */
11079         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11080                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11081     
11082         pnum = parms[0]; 
11083         aopOp (pnum, ic, FALSE, FALSE);
11084         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11085         freeAsmop (pnum, NULL, ic, FALSE);
11086         emitcode ("lcall","NatLib_LoadPrimitive");
11087         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11088         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11089             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11090                 for (i = (size-1) ; i >= 0 ; i-- ) {
11091                         emitcode ("push","a%s",javaRet[i]);
11092                 }
11093                 for (i=0; i < size ; i++ ) {
11094                         emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11095                 }
11096         } else {
11097                 for (i = 0 ; i < size ; i++ ) {
11098                         aopPut(AOP(result),javaRet[i],i);
11099                 }
11100         }    
11101         freeAsmop (result, NULL, ic, FALSE);
11102         unsavermask(rsave);
11103 }
11104
11105 /*-----------------------------------------------------------------*/
11106 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11107 /*-----------------------------------------------------------------*/
11108 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11109 {
11110         bitVect *rsave ;
11111         operand *pnum, *result;
11112         int size = 3;
11113         int i;
11114     
11115         assert (nparms==1);
11116         /* save registers that need to be saved */
11117         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11118                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11119     
11120         pnum = parms[0]; 
11121         aopOp (pnum, ic, FALSE, FALSE);
11122         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11123         freeAsmop (pnum, NULL, ic, FALSE);
11124         emitcode ("lcall","NatLib_LoadPointer");
11125         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11126         if (AOP_TYPE(result)!=AOP_STR) {
11127                 for (i = 0 ; i < size ; i++ ) {
11128                         aopPut(AOP(result),fReturn[i],i);
11129                 }
11130         }    
11131         freeAsmop (result, NULL, ic, FALSE);
11132         unsavermask(rsave);
11133 }
11134
11135 /*-----------------------------------------------------------------*/
11136 /* genNatLibInstallStateBlock -                                    */
11137 /*-----------------------------------------------------------------*/
11138 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
11139                                        operand **parms, const char *name)
11140 {
11141         bitVect *rsave ;
11142         operand *psb, *handle;
11143         assert (nparms==2);
11144
11145         /* save registers that need to be saved */
11146         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11147                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11148         psb = parms[0];
11149         handle = parms[1];
11150
11151         /* put pointer to state block into DPTR1 */
11152         aopOp (psb, ic, FALSE, FALSE);
11153         if (AOP_TYPE (psb) == AOP_IMMD) {
11154                 emitcode ("mov","dps,#1");
11155                 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11156                 emitcode ("mov","dps,#0");
11157         } else {
11158                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11159                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11160                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11161         }
11162         freeAsmop (psb, NULL, ic, FALSE);
11163
11164         /* put libraryID into DPTR */
11165         emitcode ("mov","dptr,#LibraryID");
11166
11167         /* put handle into r3:r2 */
11168         aopOp (handle, ic, FALSE, FALSE);
11169         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11170                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));  
11171                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11172                 emitcode ("pop","ar3");
11173                 emitcode ("pop","ar2");
11174         } else {        
11175                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));        
11176                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11177         }
11178         freeAsmop (psb, NULL, ic, FALSE);
11179
11180         /* make the call */
11181         emitcode ("lcall","NatLib_Install%sStateBlock",name);
11182
11183         /* put return value into place*/
11184         _G.accInUse++;
11185         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11186         _G.accInUse--;
11187         aopPut(AOP(IC_RESULT(ic)),"a",0);
11188         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11189         unsavermask(rsave);
11190 }
11191
11192 /*-----------------------------------------------------------------*/
11193 /* genNatLibRemoveStateBlock -                                     */
11194 /*-----------------------------------------------------------------*/
11195 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11196 {
11197         bitVect *rsave ;
11198
11199         assert(nparms==0);
11200
11201         /* save registers that need to be saved */
11202         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11203                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11204
11205         /* put libraryID into DPTR */
11206         emitcode ("mov","dptr,#LibraryID");
11207         /* make the call */
11208         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11209         unsavermask(rsave);
11210 }
11211
11212 /*-----------------------------------------------------------------*/
11213 /* genNatLibGetStateBlock -                                        */
11214 /*-----------------------------------------------------------------*/
11215 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11216                                    operand **parms,const char *name)
11217 {
11218         bitVect *rsave ;
11219         symbol *lbl = newiTempLabel(NULL);
11220         
11221         assert(nparms==0);
11222         /* save registers that need to be saved */
11223         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11224                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11225
11226         /* put libraryID into DPTR */
11227         emitcode ("mov","dptr,#LibraryID");
11228         /* make the call */
11229         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11230         emitcode ("jnz","!tlabel",lbl->key+100);
11231
11232         /* put return value into place */
11233         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11234         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11235                 emitcode ("push","ar3");
11236                 emitcode ("push","ar2");
11237                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11238                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11239         } else {
11240                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11241                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11242         }
11243         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11244         emitcode ("","!tlabeldef",lbl->key+100);
11245         unsavermask(rsave);
11246 }
11247
11248 /*-----------------------------------------------------------------*/
11249 /* genMMMalloc -                                                   */
11250 /*-----------------------------------------------------------------*/
11251 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11252                          int size, const char *name)
11253 {
11254         bitVect *rsave ;
11255         operand *bsize;
11256         symbol *rsym;
11257         symbol *lbl = newiTempLabel(NULL);
11258
11259         assert (nparms == 1);
11260         /* save registers that need to be saved */
11261         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11262                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11263         
11264         bsize=parms[0];
11265         aopOp (bsize,ic,FALSE,FALSE);
11266
11267         /* put the size in R4-R2 */
11268         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11269                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11270                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11271                 if (size==3) {
11272                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11273                         emitcode("pop","ar4");
11274                 }
11275                 emitcode("pop","ar3");
11276                 emitcode("pop","ar2");          
11277         } else {
11278                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11279                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11280                 if (size==3) {
11281                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11282                 }
11283         }
11284         freeAsmop (bsize, NULL, ic, FALSE);
11285
11286         /* make the call */
11287         emitcode ("lcall","MM_%s",name);
11288         emitcode ("jz","!tlabel",lbl->key+100);
11289         emitcode ("mov","r2,#!constbyte",0xff);
11290         emitcode ("mov","r3,#!constbyte",0xff);
11291         emitcode ("","!tlabeldef",lbl->key+100);
11292         /* we don't care about the pointer : we just save the handle */
11293         rsym = OP_SYMBOL(IC_RESULT(ic));
11294         if (rsym->liveFrom != rsym->liveTo) {
11295                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11296                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11297                         emitcode ("push","ar3");
11298                         emitcode ("push","ar2");
11299                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11300                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11301                 } else {
11302                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
11303                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
11304                 }
11305                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11306         }
11307         unsavermask(rsave);
11308 }
11309
11310 /*-----------------------------------------------------------------*/
11311 /* genMMDeref -                                                    */
11312 /*-----------------------------------------------------------------*/
11313 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11314 {
11315         bitVect *rsave ;
11316         operand *handle;
11317
11318         assert (nparms == 1);
11319         /* save registers that need to be saved */
11320         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11321                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11322         
11323         handle=parms[0];
11324         aopOp (handle,ic,FALSE,FALSE);
11325
11326         /* put the size in R4-R2 */
11327         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11328                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11329                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11330                 emitcode("pop","ar3");
11331                 emitcode("pop","ar2");          
11332         } else {
11333                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11334                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11335         }
11336         freeAsmop (handle, NULL, ic, FALSE);
11337
11338         /* make the call */
11339         emitcode ("lcall","MM_Deref");
11340         
11341         {
11342                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11343                 if (rsym->liveFrom != rsym->liveTo) {                   
11344                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11345                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11346                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11347                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11348                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11349                         }
11350                 }
11351         }
11352         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11353         unsavermask(rsave);
11354 }
11355
11356 /*-----------------------------------------------------------------*/
11357 /* genMMUnrestrictedPersist -                                      */
11358 /*-----------------------------------------------------------------*/
11359 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11360 {
11361         bitVect *rsave ;
11362         operand *handle;
11363
11364         assert (nparms == 1);
11365         /* save registers that need to be saved */
11366         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11367                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11368         
11369         handle=parms[0];
11370         aopOp (handle,ic,FALSE,FALSE);
11371
11372         /* put the size in R3-R2 */
11373         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11374                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11375                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11376                 emitcode("pop","ar3");
11377                 emitcode("pop","ar2");          
11378         } else {
11379                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11380                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11381         }
11382         freeAsmop (handle, NULL, ic, FALSE);
11383
11384         /* make the call */
11385         emitcode ("lcall","MM_UnrestrictedPersist");
11386
11387         {
11388                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11389                 if (rsym->liveFrom != rsym->liveTo) {   
11390                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11391                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11392                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11393                 }
11394         }
11395         unsavermask(rsave);
11396 }
11397
11398 /*-----------------------------------------------------------------*/
11399 /* genSystemExecJavaProcess -                                      */
11400 /*-----------------------------------------------------------------*/
11401 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
11402 {
11403         bitVect *rsave ;
11404         operand *handle, *pp;
11405
11406         assert (nparms==2);
11407         /* save registers that need to be saved */
11408         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11409                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11410         
11411         pp = parms[0];
11412         handle = parms[1];
11413         
11414         /* put the handle in R3-R2 */
11415         aopOp (handle,ic,FALSE,FALSE);
11416         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11417                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11418                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11419                 emitcode("pop","ar3");
11420                 emitcode("pop","ar2");          
11421         } else {
11422                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11423                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11424         }
11425         freeAsmop (handle, NULL, ic, FALSE);
11426         
11427         /* put pointer in DPTR */
11428         aopOp (pp,ic,FALSE,FALSE);
11429         if (AOP_TYPE(pp) == AOP_IMMD) {
11430                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));          
11431         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
11432                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11433                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11434                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11435         }
11436         freeAsmop (handle, NULL, ic, FALSE);
11437
11438         /* make the call */
11439         emitcode ("lcall","System_ExecJavaProcess");
11440         
11441         /* put result in place */
11442         {
11443                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11444                 if (rsym->liveFrom != rsym->liveTo) {   
11445                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11446                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11447                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11448                 }
11449         }
11450         
11451         unsavermask(rsave);
11452 }
11453
11454 /*-----------------------------------------------------------------*/
11455 /* genSystemRTCRegisters -                                         */
11456 /*-----------------------------------------------------------------*/
11457 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
11458                                   char *name)
11459 {
11460         bitVect *rsave ;
11461         operand *pp;
11462
11463         assert (nparms==1);
11464         /* save registers that need to be saved */
11465         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11466                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11467         
11468         pp=parms[0];
11469         /* put pointer in DPTR */
11470         aopOp (pp,ic,FALSE,FALSE);
11471         if (AOP_TYPE (pp) == AOP_IMMD) {
11472                 emitcode ("mov","dps,#1");
11473                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
11474                 emitcode ("mov","dps,#0");
11475         } else {
11476                 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11477                 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11478                 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11479         }
11480         freeAsmop (pp, NULL, ic, FALSE);
11481
11482         /* make the call */
11483         emitcode ("lcall","System_%sRTCRegisters",name);
11484
11485         unsavermask(rsave);
11486 }
11487
11488 /*-----------------------------------------------------------------*/
11489 /* genSystemThreadSleep -                                          */
11490 /*-----------------------------------------------------------------*/
11491 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
11492 {
11493         bitVect *rsave ;
11494         operand *to, *s;
11495
11496         assert (nparms==1);
11497         /* save registers that need to be saved */
11498         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11499                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11500
11501         to = parms[0];
11502         aopOp(to,ic,FALSE,FALSE);
11503         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
11504             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
11505                 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11506                 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11507                 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11508                 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11509                 emitcode ("pop","ar3");
11510                 emitcode ("pop","ar2");
11511                 emitcode ("pop","ar1");
11512                 emitcode ("pop","ar0");
11513         } else {
11514                 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11515                 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11516                 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11517                 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11518         }
11519         freeAsmop (to, NULL, ic, FALSE);
11520
11521         /* suspend in acc */
11522         s = parms[1];
11523         aopOp(s,ic,FALSE,FALSE);
11524         emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
11525         freeAsmop (s, NULL, ic, FALSE);
11526
11527         /* make the call */
11528         emitcode ("lcall","System_%s",name);
11529
11530         unsavermask(rsave);
11531 }
11532
11533 /*-----------------------------------------------------------------*/
11534 /* genSystemThreadResume -                                         */
11535 /*-----------------------------------------------------------------*/
11536 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
11537 {
11538         bitVect *rsave ;
11539         operand *tid,*pid;
11540
11541         assert (nparms==2);
11542         /* save registers that need to be saved */
11543         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11544                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11545         
11546         tid = parms[0];
11547         pid = parms[1];
11548         
11549         /* PID in R0 */
11550         aopOp(pid,ic,FALSE,FALSE);
11551         emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11552         freeAsmop (pid, NULL, ic, FALSE);
11553         
11554         /* tid into ACC */
11555         aopOp(tid,ic,FALSE,FALSE);
11556         emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
11557         freeAsmop (tid, NULL, ic, FALSE);
11558         
11559         emitcode ("lcall","System_ThreadResume");
11560
11561         /* put result into place */
11562         {
11563                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11564                 if (rsym->liveFrom != rsym->liveTo) {   
11565                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11566                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11567                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11568                 }
11569         }
11570         unsavermask(rsave);
11571 }
11572
11573 /*-----------------------------------------------------------------*/
11574 /* genSystemProcessResume -                                        */
11575 /*-----------------------------------------------------------------*/
11576 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
11577 {
11578         bitVect *rsave ;
11579         operand *pid;
11580
11581         assert (nparms==1);
11582         /* save registers that need to be saved */
11583         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11584                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11585         
11586         pid = parms[0];
11587         
11588         /* pid into ACC */
11589         aopOp(pid,ic,FALSE,FALSE);
11590         emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11591         freeAsmop (pid, NULL, ic, FALSE);
11592         
11593         emitcode ("lcall","System_ProcessResume");
11594
11595         unsavermask(rsave);
11596 }
11597
11598 /*-----------------------------------------------------------------*/
11599 /* genSystem -                                                     */
11600 /*-----------------------------------------------------------------*/
11601 static void genSystem (iCode *ic,int nparms,char *name)
11602 {
11603         assert(nparms == 0);
11604
11605         emitcode ("lcall","System_%s",name);
11606 }
11607
11608 /*-----------------------------------------------------------------*/
11609 /* genSystemPoll -                                                  */
11610 /*-----------------------------------------------------------------*/
11611 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
11612 {
11613         bitVect *rsave ;
11614         operand *fp;
11615
11616         assert (nparms==1);
11617         /* save registers that need to be saved */
11618         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11619                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11620
11621         fp = parms[0];
11622         aopOp (fp,ic,FALSE,FALSE);
11623         if (AOP_TYPE (fp) == AOP_IMMD) {
11624                 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
11625         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
11626                 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
11627                 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
11628                 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
11629         }
11630         freeAsmop (fp, NULL, ic, FALSE);
11631
11632         emitcode ("lcall","System_%sPoll",name);
11633
11634         /* put result into place */
11635         {
11636                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11637                 if (rsym->liveFrom != rsym->liveTo) {   
11638                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11639                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11640                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11641                 }
11642         }
11643         unsavermask(rsave);
11644 }
11645
11646 /*-----------------------------------------------------------------*/
11647 /* genSystemGetCurrentID -                                         */
11648 /*-----------------------------------------------------------------*/
11649 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
11650 {
11651         assert (nparms==0);
11652
11653         emitcode ("lcall","System_GetCurrent%sId",name);
11654         /* put result into place */
11655         {
11656                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11657                 if (rsym->liveFrom != rsym->liveTo) {   
11658                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11659                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11660                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11661                 }
11662         }
11663 }
11664
11665 /*-----------------------------------------------------------------*/
11666 /* genBuiltIn - calls the appropriate function to  generating code */
11667 /* for a built in function                                         */
11668 /*-----------------------------------------------------------------*/
11669 static void genBuiltIn (iCode *ic)
11670 {
11671         operand *bi_parms[MAX_BUILTIN_ARGS];
11672         int nbi_parms;
11673         iCode *bi_iCode;
11674         symbol *bif;
11675
11676         /* get all the arguments for a built in function */
11677         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
11678
11679         /* which function is it */
11680         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
11681         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
11682                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
11683         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
11684                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
11685         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
11686                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
11687         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
11688                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
11689         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
11690                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
11691         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
11692                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
11693         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
11694                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
11695         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
11696                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11697         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
11698                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11699         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
11700                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
11701         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
11702                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
11703         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
11704                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11705         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
11706                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11707         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
11708                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
11709         } else if (strcmp(bif->name,"MM_Malloc")==0) {
11710                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
11711         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
11712                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
11713         } else if (strcmp(bif->name,"MM_Free")==0) {
11714                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
11715         } else if (strcmp(bif->name,"MM_Deref")==0) {
11716                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
11717         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
11718                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
11719         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
11720                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
11721         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
11722                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
11723         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
11724                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
11725         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
11726                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
11727         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
11728                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
11729         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
11730                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
11731         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
11732                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
11733         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11734                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11735         } else if (strcmp(bif->name,"System_SaveThread")==0) {
11736                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11737         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11738                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11739         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
11740                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
11741         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
11742                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
11743         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
11744                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
11745         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
11746                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
11747         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
11748                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
11749         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
11750                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
11751         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
11752                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
11753         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
11754                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
11755         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
11756                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
11757         } else {
11758                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
11759                 return ;
11760         }
11761         return ;    
11762 }
11763
11764 /*-----------------------------------------------------------------*/
11765 /* gen390Code - generate code for Dallas 390 based controllers     */
11766 /*-----------------------------------------------------------------*/
11767 void
11768 gen390Code (iCode * lic)
11769 {
11770   iCode *ic;
11771   int cln = 0;
11772
11773   lineHead = lineCurr = NULL;
11774
11775   if (options.model == MODEL_FLAT24) {
11776     fReturnSizeDS390 = 5;
11777     fReturn = fReturn24;
11778   } else {
11779     fReturnSizeDS390 = 4;
11780     fReturn = fReturn16;
11781     options.stack10bit=0;
11782   }
11783 #if 0
11784   //REMOVE ME!!!
11785   /* print the allocation information */
11786   if (allocInfo)
11787     printAllocInfo (currFunc, codeOutFile);
11788 #endif
11789   /* if debug information required */
11790   if (options.debug && currFunc)
11791     {
11792       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
11793       _G.debugLine = 1;
11794       if (IS_STATIC (currFunc->etype))
11795         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
11796       else
11797         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
11798       _G.debugLine = 0;
11799     }
11800   /* stack pointer name */
11801   if (options.useXstack)
11802     spname = "_spx";
11803   else
11804     spname = "sp";
11805
11806
11807   for (ic = lic; ic; ic = ic->next)
11808     {
11809
11810       if (cln != ic->lineno)
11811         {
11812           if (options.debug)
11813             {
11814               _G.debugLine = 1;
11815               emitcode ("", "C$%s$%d$%d$%d ==.",
11816                         FileBaseName (ic->filename), ic->lineno,
11817                         ic->level, ic->block);
11818               _G.debugLine = 0;
11819             }
11820           emitcode (";", "%s %d", ic->filename, ic->lineno);
11821           cln = ic->lineno;
11822         }
11823       /* if the result is marked as
11824          spilt and rematerializable or code for
11825          this has already been generated then
11826          do nothing */
11827       if (resultRemat (ic) || ic->generated)
11828         continue;
11829
11830       /* depending on the operation */
11831       switch (ic->op)
11832         {
11833         case '!':
11834           genNot (ic);
11835           break;
11836
11837         case '~':
11838           genCpl (ic);
11839           break;
11840
11841         case UNARYMINUS:
11842           genUminus (ic);
11843           break;
11844
11845         case IPUSH:
11846           genIpush (ic);
11847           break;
11848
11849         case IPOP:
11850           /* IPOP happens only when trying to restore a
11851              spilt live range, if there is an ifx statement
11852              following this pop then the if statement might
11853              be using some of the registers being popped which
11854              would destory the contents of the register so
11855              we need to check for this condition and handle it */
11856           if (ic->next &&
11857               ic->next->op == IFX &&
11858               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11859             genIfx (ic->next, ic);
11860           else
11861             genIpop (ic);
11862           break;
11863
11864         case CALL:
11865           genCall (ic);
11866           break;
11867
11868         case PCALL:
11869           genPcall (ic);
11870           break;
11871
11872         case FUNCTION:
11873           genFunction (ic);
11874           break;
11875
11876         case ENDFUNCTION:
11877           genEndFunction (ic);
11878           break;
11879
11880         case RETURN:
11881           genRet (ic);
11882           break;
11883
11884         case LABEL:
11885           genLabel (ic);
11886           break;
11887
11888         case GOTO:
11889           genGoto (ic);
11890           break;
11891
11892         case '+':
11893           genPlus (ic);
11894           break;
11895
11896         case '-':
11897           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11898             genMinus (ic);
11899           break;
11900
11901         case '*':
11902           genMult (ic);
11903           break;
11904
11905         case '/':
11906           genDiv (ic);
11907           break;
11908
11909         case '%':
11910           genMod (ic);
11911           break;
11912
11913         case '>':
11914           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11915           break;
11916
11917         case '<':
11918           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11919           break;
11920
11921         case LE_OP:
11922         case GE_OP:
11923         case NE_OP:
11924
11925           /* note these two are xlated by algebraic equivalence
11926              during parsing SDCC.y */
11927           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11928                   "got '>=' or '<=' shouldn't have come here");
11929           break;
11930
11931         case EQ_OP:
11932           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11933           break;
11934
11935         case AND_OP:
11936           genAndOp (ic);
11937           break;
11938
11939         case OR_OP:
11940           genOrOp (ic);
11941           break;
11942
11943         case '^':
11944           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11945           break;
11946
11947         case '|':
11948           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11949           break;
11950
11951         case BITWISEAND:
11952           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11953           break;
11954
11955         case INLINEASM:
11956           genInline (ic);
11957           break;
11958
11959         case RRC:
11960           genRRC (ic);
11961           break;
11962
11963         case RLC:
11964           genRLC (ic);
11965           break;
11966
11967         case GETHBIT:
11968           genGetHbit (ic);
11969           break;
11970
11971         case LEFT_OP:
11972           genLeftShift (ic);
11973           break;
11974
11975         case RIGHT_OP:
11976           genRightShift (ic);
11977           break;
11978
11979         case GET_VALUE_AT_ADDRESS:
11980           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_LEFT(ic)))));
11981           break;
11982
11983         case '=':
11984           if (POINTER_SET (ic))
11985             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11986           else
11987             genAssign (ic);
11988           break;
11989
11990         case IFX:
11991           genIfx (ic, NULL);
11992           break;
11993
11994         case ADDRESS_OF:
11995           genAddrOf (ic);
11996           break;
11997
11998         case JUMPTABLE:
11999           genJumpTab (ic);
12000           break;
12001
12002         case CAST:
12003           genCast (ic);
12004           break;
12005
12006         case RECEIVE:
12007           genReceive (ic);
12008           break;
12009
12010         case SEND:
12011           if (ic->builtinSEND) genBuiltIn(ic);
12012           else addSet (&_G.sendSet, ic);
12013           break;
12014
12015         case ARRAYINIT:
12016             genArrayInit(ic);
12017             break;
12018             
12019         default:
12020           ic = ic;
12021         }
12022     }
12023
12024
12025   /* now we are ready to call the
12026      peep hole optimizer */
12027   if (!options.nopeep)
12028     peepHole (&lineHead);
12029
12030   /* now do the actual printing */
12031   printLine (lineHead, codeOutFile);
12032   return;
12033 }