fixed bug #503216
[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
1696   D (emitcode (";", "genCpl ");
1697     );
1698
1699
1700   /* assign asmOps to operand & result */
1701   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1702   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1703
1704   /* if both are in bit space then
1705      a special case */
1706   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1707       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1708     {
1709
1710       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1711       emitcode ("cpl", "c");
1712       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1713       goto release;
1714     }
1715
1716   size = AOP_SIZE (IC_RESULT (ic));
1717   _startLazyDPSEvaluation ();
1718   while (size--)
1719     {
1720       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1721       MOVA (l);
1722       emitcode ("cpl", "a");
1723       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1724     }
1725   _endLazyDPSEvaluation ();
1726
1727
1728 release:
1729   /* release the aops */
1730   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1731   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1732 }
1733
1734 /*-----------------------------------------------------------------*/
1735 /* genUminusFloat - unary minus for floating points                */
1736 /*-----------------------------------------------------------------*/
1737 static void
1738 genUminusFloat (operand * op, operand * result)
1739 {
1740   int size, offset = 0;
1741   char *l;
1742   /* for this we just need to flip the
1743      first it then copy the rest in place */
1744   D (emitcode (";", "genUminusFloat");
1745     );
1746
1747   _startLazyDPSEvaluation ();
1748   size = AOP_SIZE (op) - 1;
1749   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1750   MOVA (l);
1751
1752   emitcode ("cpl", "acc.7");
1753   aopPut (AOP (result), "a", 3);
1754
1755   while (size--)
1756     {
1757       aopPut (AOP (result),
1758               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1759               offset);
1760       offset++;
1761     }
1762   _endLazyDPSEvaluation ();
1763 }
1764
1765 /*-----------------------------------------------------------------*/
1766 /* genUminus - unary minus code generation                         */
1767 /*-----------------------------------------------------------------*/
1768 static void
1769 genUminus (iCode * ic)
1770 {
1771   int offset, size;
1772   sym_link *optype, *rtype;
1773
1774   D (emitcode (";", "genUminus ");
1775     );
1776
1777
1778   /* assign asmops */
1779   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1780   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1781
1782   /* if both in bit space then special
1783      case */
1784   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1785       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1786     {
1787
1788       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1789       emitcode ("cpl", "c");
1790       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1791       goto release;
1792     }
1793
1794   optype = operandType (IC_LEFT (ic));
1795   rtype = operandType (IC_RESULT (ic));
1796
1797   /* if float then do float stuff */
1798   if (IS_FLOAT (optype))
1799     {
1800       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1801       goto release;
1802     }
1803
1804   /* otherwise subtract from zero */
1805   size = AOP_SIZE (IC_LEFT (ic));
1806   offset = 0;
1807   _startLazyDPSEvaluation ();
1808   while (size--)
1809     {
1810       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1811       if (!strcmp (l, "a"))
1812         {
1813           if (offset == 0)
1814             SETC;
1815           emitcode ("cpl", "a");
1816           emitcode ("addc", "a,#0");
1817         }
1818       else
1819         {
1820           if (offset == 0)
1821             CLRC;
1822           emitcode ("clr", "a");
1823           emitcode ("subb", "a,%s", l);
1824         }
1825       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1826     }
1827   _endLazyDPSEvaluation ();
1828
1829   /* if any remaining bytes in the result */
1830   /* we just need to propagate the sign   */
1831   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1832     {
1833       emitcode ("rlc", "a");
1834       emitcode ("subb", "a,acc");
1835       while (size--)
1836         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1837     }
1838
1839 release:
1840   /* release the aops */
1841   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1842   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1843 }
1844
1845 /*-----------------------------------------------------------------*/
1846 /* savermask - saves registers in the mask                         */
1847 /*-----------------------------------------------------------------*/
1848 static void savermask(bitVect *rs_mask)
1849 {
1850     int i;
1851     if (options.useXstack) {
1852         if (bitVectBitValue (rs_mask, R0_IDX))
1853             emitcode ("mov", "b,r0");
1854         emitcode ("mov", "r0,%s", spname);
1855         for (i = 0; i < ds390_nRegs; i++) {
1856             if (bitVectBitValue (rs_mask, i)) {
1857                 if (i == R0_IDX)
1858                     emitcode ("mov", "a,b");
1859                 else
1860                     emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1861                 emitcode ("movx", "@r0,a");
1862                 emitcode ("inc", "r0");
1863             }
1864         }
1865         emitcode ("mov", "%s,r0", spname);
1866         if (bitVectBitValue (rs_mask, R0_IDX))
1867             emitcode ("mov", "r0,b");
1868     } else {
1869         for (i = 0; i < ds390_nRegs; i++) {
1870             if (bitVectBitValue (rs_mask, i))
1871                 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1872         }
1873     }
1874 }
1875
1876 /*-----------------------------------------------------------------*/
1877 /* saveRegisters - will look for a call and save the registers     */
1878 /*-----------------------------------------------------------------*/
1879 static void
1880 saveRegisters (iCode * lic)
1881 {
1882   iCode *ic;
1883   bitVect *rsave;
1884
1885   /* look for call */
1886   for (ic = lic; ic; ic = ic->next)
1887     if (ic->op == CALL || ic->op == PCALL)
1888       break;
1889
1890   if (!ic)
1891     {
1892       fprintf (stderr, "found parameter push with no function call\n");
1893       return;
1894     }
1895
1896   /* if the registers have been saved already then
1897      do nothing */
1898   if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
1899
1900   /* special case if DPTR alive across a function call then must save it 
1901      even though callee saves */
1902   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1903       int i =0;
1904       rsave = newBitVect(ic->rMask->size);
1905       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1906           if (bitVectBitValue(ic->rMask,i))
1907               rsave = bitVectSetBit(rsave,i);
1908       }
1909       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1910   } else {
1911     /* safe the registers in use at this time but skip the
1912        ones for the result */
1913     rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1914                            ds390_rUmaskForOp (IC_RESULT(ic)));
1915   }
1916   ic->regsSaved = 1;
1917   savermask(rsave);
1918 }
1919
1920 /*-----------------------------------------------------------------*/
1921 /* usavermask - restore registers with mask                        */
1922 /*-----------------------------------------------------------------*/
1923 static void unsavermask(bitVect *rs_mask)
1924 {
1925     int i;
1926     if (options.useXstack) {
1927         emitcode ("mov", "r0,%s", spname);
1928         for (i = ds390_nRegs; i >= 0; i--) {
1929             if (bitVectBitValue (rs_mask, i)) {
1930                 emitcode ("dec", "r0");
1931                 emitcode ("movx", "a,@r0");
1932                 if (i == R0_IDX)
1933                     emitcode ("mov", "b,a");
1934                 else
1935                     emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1936             }       
1937         }
1938         emitcode ("mov", "%s,r0", spname);
1939         if (bitVectBitValue (rs_mask, R0_IDX))
1940             emitcode ("mov", "r0,b");
1941     } else {
1942         for (i = ds390_nRegs; i >= 0; i--) {
1943             if (bitVectBitValue (rs_mask, i))
1944                 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1945         }
1946     }
1947 }
1948
1949 /*-----------------------------------------------------------------*/
1950 /* unsaveRegisters - pop the pushed registers                      */
1951 /*-----------------------------------------------------------------*/
1952 static void
1953 unsaveRegisters (iCode * ic)
1954 {
1955   bitVect *rsave;
1956
1957   if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
1958       int i =0;
1959       rsave = newBitVect(ic->rMask->size);
1960       for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
1961           if (bitVectBitValue(ic->rMask,i))
1962               rsave = bitVectSetBit(rsave,i);
1963       }
1964       rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
1965   } else {
1966     /* restore the registers in use at this time but skip the
1967        ones for the result */
1968     rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
1969                            ds390_rUmaskForOp (IC_RESULT(ic)));
1970   }
1971   unsavermask(rsave);
1972 }
1973
1974
1975 /*-----------------------------------------------------------------*/
1976 /* pushSide -                */
1977 /*-----------------------------------------------------------------*/
1978 static void
1979 pushSide (operand * oper, int size)
1980 {
1981   int offset = 0;
1982   _startLazyDPSEvaluation ();
1983   while (size--)
1984     {
1985       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1986       if (AOP_TYPE (oper) != AOP_REG &&
1987           AOP_TYPE (oper) != AOP_DIR &&
1988           strcmp (l, "a"))
1989         {
1990           emitcode ("mov", "a,%s", l);
1991           emitcode ("push", "acc");
1992         }
1993       else
1994         emitcode ("push", "%s", l);
1995     }
1996   _endLazyDPSEvaluation ();
1997 }
1998
1999 /*-----------------------------------------------------------------*/
2000 /* assignResultValue -               */
2001 /*-----------------------------------------------------------------*/
2002 static void
2003 assignResultValue (operand * oper)
2004 {
2005   int offset = 0;
2006   int size = AOP_SIZE (oper);
2007
2008   _startLazyDPSEvaluation ();
2009   while (size--)
2010     {
2011       aopPut (AOP (oper), fReturn[offset], offset);
2012       offset++;
2013     }
2014   _endLazyDPSEvaluation ();
2015 }
2016
2017
2018 /*-----------------------------------------------------------------*/
2019 /* genXpush - pushes onto the external stack                       */
2020 /*-----------------------------------------------------------------*/
2021 static void
2022 genXpush (iCode * ic)
2023 {
2024   asmop *aop = newAsmop (0);
2025   regs *r;
2026   int size, offset = 0;
2027
2028   D (emitcode (";", "genXpush ");
2029     );
2030
2031   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2032   r = getFreePtr (ic, &aop, FALSE);
2033
2034
2035   emitcode ("mov", "%s,_spx", r->name);
2036
2037   size = AOP_SIZE (IC_LEFT (ic));
2038   _startLazyDPSEvaluation ();
2039   while (size--)
2040     {
2041
2042       char *l = aopGet (AOP (IC_LEFT (ic)),
2043                         offset++, FALSE, FALSE, TRUE);
2044       MOVA (l);
2045       emitcode ("movx", "@%s,a", r->name);
2046       emitcode ("inc", "%s", r->name);
2047
2048     }
2049   _endLazyDPSEvaluation ();
2050
2051
2052   emitcode ("mov", "_spx,%s", r->name);
2053
2054   freeAsmop (NULL, aop, ic, TRUE);
2055   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2056 }
2057
2058 /*-----------------------------------------------------------------*/
2059 /* genIpush - genrate code for pushing this gets a little complex  */
2060 /*-----------------------------------------------------------------*/
2061 static void
2062 genIpush (iCode * ic)
2063 {
2064   int size, offset = 0;
2065   char *l;
2066
2067   D (emitcode (";", "genIpush ");
2068     );
2069
2070   /* if this is not a parm push : ie. it is spill push
2071      and spill push is always done on the local stack */
2072   if (!ic->parmPush)
2073     {
2074
2075       /* and the item is spilt then do nothing */
2076       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2077         return;
2078
2079       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2080       size = AOP_SIZE (IC_LEFT (ic));
2081       /* push it on the stack */
2082       _startLazyDPSEvaluation ();
2083       while (size--)
2084         {
2085           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
2086           if (*l == '#')
2087             {
2088               MOVA (l);
2089               l = "acc";
2090             }
2091           emitcode ("push", "%s", l);
2092         }
2093       _endLazyDPSEvaluation ();
2094       return;
2095     }
2096
2097   /* this is a paramter push: in this case we call
2098      the routine to find the call and save those
2099      registers that need to be saved */
2100   saveRegisters (ic);
2101
2102   /* if use external stack then call the external
2103      stack pushing routine */
2104   if (options.useXstack)
2105     {
2106       genXpush (ic);
2107       return;
2108     }
2109
2110   /* then do the push */
2111   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2112
2113   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2114   size = AOP_SIZE (IC_LEFT (ic));
2115
2116   _startLazyDPSEvaluation ();
2117   while (size--)
2118     {
2119       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2120       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2121           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2122           strcmp (l, "a"))
2123         {
2124           emitcode ("mov", "a,%s", l);
2125           emitcode ("push", "acc");
2126         }
2127       else
2128         emitcode ("push", "%s", l);
2129     }
2130   _endLazyDPSEvaluation ();
2131
2132   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2133 }
2134
2135 /*-----------------------------------------------------------------*/
2136 /* genIpop - recover the registers: can happen only for spilling   */
2137 /*-----------------------------------------------------------------*/
2138 static void
2139 genIpop (iCode * ic)
2140 {
2141   int size, offset;
2142
2143   D (emitcode (";", "genIpop ");
2144     );
2145
2146
2147   /* if the temp was not pushed then */
2148   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2149     return;
2150
2151   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2152   size = AOP_SIZE (IC_LEFT (ic));
2153   offset = (size - 1);
2154   _startLazyDPSEvaluation ();
2155   while (size--)
2156     {
2157       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2158                                      FALSE, TRUE, TRUE));
2159     }
2160   _endLazyDPSEvaluation ();
2161
2162   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2163 }
2164
2165 /*-----------------------------------------------------------------*/
2166 /* unsaveRBank - restores the resgister bank from stack            */
2167 /*-----------------------------------------------------------------*/
2168 static void
2169 unsaveRBank (int bank, iCode * ic, bool popPsw)
2170 {
2171   int i;
2172   asmop *aop = NULL;
2173   regs *r = NULL;
2174
2175   if (options.useXstack)
2176   {
2177       if (!ic)
2178       {
2179           /* Assume r0 is available for use. */
2180           r = ds390_regWithIdx (R0_IDX);;          
2181       } 
2182       else
2183       {
2184           aop = newAsmop (0);
2185           r = getFreePtr (ic, &aop, FALSE);
2186       }
2187       emitcode ("mov", "%s,_spx", r->name);      
2188   }
2189   
2190   if (popPsw)
2191     {
2192       if (options.useXstack)
2193       {
2194           emitcode ("movx", "a,@%s", r->name);
2195           emitcode ("mov", "psw,a");
2196           emitcode ("dec", "%s", r->name);
2197         }
2198       else
2199       {
2200         emitcode ("pop", "psw");
2201       }
2202     }
2203
2204   for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2205     {
2206       if (options.useXstack)
2207         {
2208           emitcode ("movx", "a,@%s", r->name);
2209           emitcode ("mov", "(%s+%d),a",
2210                     regs390[i].base, 8 * bank + regs390[i].offset);
2211           emitcode ("dec", "%s", r->name);
2212
2213         }
2214       else
2215         emitcode ("pop", "(%s+%d)",
2216                   regs390[i].base, 8 * bank + regs390[i].offset);
2217     }
2218
2219   if (options.useXstack)
2220     {
2221       emitcode ("mov", "_spx,%s", r->name);
2222     }
2223     
2224   if (aop)
2225   {
2226       freeAsmop (NULL, aop, ic, TRUE);  
2227   }    
2228 }
2229
2230 /*-----------------------------------------------------------------*/
2231 /* saveRBank - saves an entire register bank on the stack          */
2232 /*-----------------------------------------------------------------*/
2233 static void
2234 saveRBank (int bank, iCode * ic, bool pushPsw)
2235 {
2236   int i;
2237   asmop *aop = NULL;
2238   regs *r = NULL;
2239
2240   if (options.useXstack)
2241     {
2242         if (!ic)
2243         {
2244           /* Assume r0 is available for use. */
2245                   r = ds390_regWithIdx (R0_IDX);;
2246         }
2247         else
2248         {
2249           aop = newAsmop (0);
2250           r = getFreePtr (ic, &aop, FALSE);
2251         }
2252         emitcode ("mov", "%s,_spx", r->name);    
2253     }
2254
2255   for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2256     {
2257       if (options.useXstack)
2258         {
2259           emitcode ("inc", "%s", r->name);
2260           emitcode ("mov", "a,(%s+%d)",
2261                     regs390[i].base, 8 * bank + regs390[i].offset);
2262           emitcode ("movx", "@%s,a", r->name);
2263         }
2264       else
2265         emitcode ("push", "(%s+%d)",
2266                   regs390[i].base, 8 * bank + regs390[i].offset);
2267     }
2268
2269   if (pushPsw)
2270     {
2271       if (options.useXstack)
2272         {
2273           emitcode ("mov", "a,psw");
2274           emitcode ("movx", "@%s,a", r->name);
2275           emitcode ("inc", "%s", r->name);
2276           emitcode ("mov", "_spx,%s", r->name);
2277         }
2278       else
2279       {
2280         emitcode ("push", "psw");
2281       }
2282
2283       emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2284     }
2285   
2286   if (aop)
2287   {
2288        freeAsmop (NULL, aop, ic, TRUE);
2289   }    
2290     
2291   if (ic)
2292   {  
2293       ic->bankSaved = 1;
2294   }
2295 }
2296
2297 /*-----------------------------------------------------------------*/
2298 /* genCall - generates a call statement                            */
2299 /*-----------------------------------------------------------------*/
2300 static void
2301 genCall (iCode * ic)
2302 {
2303   sym_link *dtype;
2304   bool restoreBank = FALSE;
2305   bool swapBanks = FALSE;
2306
2307   D (emitcode (";", "genCall "););
2308
2309   /* if we are calling a not _naked function that is not using
2310      the same register bank then we need to save the
2311      destination registers on the stack */
2312   dtype = operandType (IC_LEFT (ic));
2313   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2314       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2315       IFFUNC_ISISR (currFunc->type))
2316   {
2317       if (!ic->bankSaved) 
2318       {
2319            /* This is unexpected; the bank should have been saved in
2320             * genFunction.
2321             */
2322            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2323            restoreBank = TRUE;
2324       }
2325       swapBanks = TRUE;
2326   }
2327   
2328     /* if caller saves & we have not saved then */
2329     if (!ic->regsSaved)
2330       saveRegisters (ic);
2331   
2332   /* if send set is not empty the assign */
2333   /* We've saved all the registers we care about;
2334   * therefore, we may clobber any register not used
2335   * in the calling convention (i.e. anything not in
2336   * fReturn.
2337   */
2338   if (_G.sendSet)
2339     {
2340       iCode *sic;
2341
2342       for (sic = setFirstItem (_G.sendSet); sic;
2343            sic = setNextItem (_G.sendSet))
2344         {
2345           int size, offset = 0;
2346
2347           // we know that dpl(hxb) is the result, so
2348           _startLazyDPSEvaluation ();
2349           size=getSize(operandType(IC_LEFT(sic)));
2350           if (size>1) {
2351             aopOp (IC_LEFT (sic), sic, FALSE, 
2352                    (IS_SYMOP(IC_LEFT(sic)) && OP_SYMBOL(IC_LEFT(sic))->ruonly ? FALSE : TRUE));
2353           } else {
2354             aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2355           }
2356           while (size--)
2357             {
2358               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2359                                 FALSE, FALSE, TRUE);
2360               if (strcmp (l, fReturn[offset]))
2361                 {
2362                   emitcode ("mov", "%s,%s",
2363                             fReturn[offset],
2364                             l);
2365                 }
2366               offset++;
2367             }
2368           _endLazyDPSEvaluation ();
2369           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2370         }
2371       _G.sendSet = NULL;
2372     }  
2373     
2374   if (swapBanks)
2375   {
2376         emitcode ("mov", "psw,#!constbyte", 
2377            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2378   }
2379
2380   /* make the call */
2381   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2382                             OP_SYMBOL (IC_LEFT (ic))->rname :
2383                             OP_SYMBOL (IC_LEFT (ic))->name));
2384
2385   if (swapBanks)
2386   {
2387        emitcode ("mov", "psw,#!constbyte", 
2388           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2389   }
2390
2391   /* if we need assign a result value */
2392   if ((IS_ITEMP (IC_RESULT (ic)) &&
2393        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2394         OP_SYMBOL (IC_RESULT (ic))->accuse ||
2395         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2396       IS_TRUE_SYMOP (IC_RESULT (ic)))
2397     {
2398       if (isOperandInFarSpace (IC_RESULT (ic))
2399           && getSize (operandType (IC_RESULT (ic))) <= 2)
2400         {
2401           int size = getSize (operandType (IC_RESULT (ic)));
2402
2403           /* Special case for 1 or 2 byte return in far space. */
2404           MOVA (fReturn[0]);
2405           if (size > 1)
2406             {
2407               emitcode ("mov", "b,%s", fReturn[1]);
2408             }
2409
2410           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2411           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2412
2413           if (size > 1)
2414             {
2415               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2416             }
2417           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2418         }
2419       else
2420         {
2421           _G.accInUse++;
2422           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2423           _G.accInUse--;
2424
2425           assignResultValue (IC_RESULT (ic));
2426
2427           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2428         }
2429     }
2430
2431   /* adjust the stack for parameters if
2432      required */
2433   if (ic->parmBytes) {
2434       int i;
2435       if (options.stack10bit) {
2436           if (ic->parmBytes <= 4) {
2437               emitcode(";","stack adjustment for parms");
2438               for (i=0; i < ic->parmBytes ; i++) {
2439                   emitcode("pop","acc");
2440               }
2441           } else {
2442               emitcode ("clr","c");
2443               emitcode ("mov","a,sp");
2444               emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2445               emitcode ("mov","sp,a");
2446               emitcode ("mov","a,esp");
2447               emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2448               emitcode ("mov","esp,a");   
2449           }
2450       } else {
2451           if (ic->parmBytes > 3) {
2452               emitcode ("mov", "a,%s", spname);
2453               emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2454               emitcode ("mov", "%s,a", spname);
2455           } else
2456               for (i = 0; i < ic->parmBytes; i++)
2457                   emitcode ("dec", "%s", spname);
2458       }
2459   }
2460
2461   /* if we hade saved some registers then unsave them */
2462   if (ic->regsSaved)
2463     unsaveRegisters (ic);
2464
2465   /* if register bank was saved then pop them */
2466   if (restoreBank)
2467     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2468 }
2469
2470 /*-----------------------------------------------------------------*/
2471 /* genPcall - generates a call by pointer statement                */
2472 /*-----------------------------------------------------------------*/
2473 static void
2474 genPcall (iCode * ic)
2475 {
2476   sym_link *dtype;
2477   symbol *rlbl = newiTempLabel (NULL);
2478   bool restoreBank=FALSE;
2479
2480   D (emitcode (";", "genPcall ");
2481     );
2482
2483
2484   /* if caller saves & we have not saved then */
2485   if (!ic->regsSaved)
2486     saveRegisters (ic);
2487
2488   /* if we are calling a function that is not using
2489      the same register bank then we need to save the
2490      destination registers on the stack */
2491   dtype = operandType (IC_LEFT (ic));
2492   if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2493       IFFUNC_ISISR (currFunc->type) &&
2494       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2495     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2496     restoreBank=TRUE;
2497   }
2498
2499   /* push the return address on to the stack */
2500   emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2501   emitcode ("push", "acc");
2502   emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2503   emitcode ("push", "acc");
2504
2505   if (options.model == MODEL_FLAT24)
2506     {
2507       emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2508       emitcode ("push", "acc");
2509     }
2510
2511   /* now push the calling address */
2512   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2513
2514   pushSide (IC_LEFT (ic), FPTRSIZE);
2515
2516   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2517
2518   /* if send set is not empty the assign */
2519   if (_G.sendSet)
2520     {
2521       iCode *sic;
2522
2523       for (sic = setFirstItem (_G.sendSet); sic;
2524            sic = setNextItem (_G.sendSet))
2525         {
2526           int size, offset = 0;
2527
2528           // we know that dpl(hxb) is the result, so
2529           _startLazyDPSEvaluation ();
2530           size=getSize(operandType(IC_LEFT(sic)));
2531           if (size>1) {
2532             aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2533           } else {
2534             aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2535           }
2536           while (size--)
2537             {
2538               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2539                                 FALSE, FALSE, TRUE);
2540               if (strcmp (l, fReturn[offset]))
2541                 {
2542                   emitcode ("mov", "%s,%s",
2543                             fReturn[offset],
2544                             l);
2545                 }
2546               offset++;
2547             }
2548           _endLazyDPSEvaluation ();
2549           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2550         }
2551       _G.sendSet = NULL;
2552     }
2553
2554   emitcode ("ret", "");
2555   emitcode ("", "!tlabeldef", (rlbl->key + 100));
2556
2557
2558   /* if we need assign a result value */
2559   if ((IS_ITEMP (IC_RESULT (ic)) &&
2560        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2561         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2562       IS_TRUE_SYMOP (IC_RESULT (ic)))
2563     {
2564
2565       _G.accInUse++;
2566       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2567       _G.accInUse--;
2568
2569       assignResultValue (IC_RESULT (ic));
2570
2571       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2572     }
2573
2574   /* adjust the stack for parameters if
2575      required */
2576   if (ic->parmBytes)
2577     {
2578       int i;
2579       if (ic->parmBytes > 3)
2580         {
2581           emitcode ("mov", "a,%s", spname);
2582           emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2583           emitcode ("mov", "%s,a", spname);
2584         }
2585       else
2586         for (i = 0; i < ic->parmBytes; i++)
2587           emitcode ("dec", "%s", spname);
2588
2589     }
2590
2591   /* if register bank was saved then unsave them */
2592   if (restoreBank)
2593     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2594   
2595   /* if we hade saved some registers then
2596      unsave them */
2597   if (ic->regsSaved)
2598     unsaveRegisters (ic);
2599
2600 }
2601
2602 /*-----------------------------------------------------------------*/
2603 /* resultRemat - result  is rematerializable                       */
2604 /*-----------------------------------------------------------------*/
2605 static int
2606 resultRemat (iCode * ic)
2607 {
2608   if (SKIP_IC (ic) || ic->op == IFX)
2609     return 0;
2610
2611   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2612     {
2613       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2614       if (sym->remat && !POINTER_SET (ic))
2615         return 1;
2616     }
2617
2618   return 0;
2619 }
2620
2621 #if defined(__BORLANDC__) || defined(_MSC_VER)
2622 #define STRCASECMP stricmp
2623 #else
2624 #define STRCASECMP strcasecmp
2625 #endif
2626
2627 /*-----------------------------------------------------------------*/
2628 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2629 /*-----------------------------------------------------------------*/
2630 static bool
2631 inExcludeList (char *s)
2632 {
2633   int i = 0;
2634
2635   if (options.excludeRegs[i] &&
2636       STRCASECMP (options.excludeRegs[i], "none") == 0)
2637     return FALSE;
2638
2639   for (i = 0; options.excludeRegs[i]; i++)
2640     {
2641       if (options.excludeRegs[i] &&
2642           STRCASECMP (s, options.excludeRegs[i]) == 0)
2643         return TRUE;
2644     }
2645   return FALSE;
2646 }
2647
2648 /*-----------------------------------------------------------------*/
2649 /* genFunction - generated code for function entry                 */
2650 /*-----------------------------------------------------------------*/
2651 static void
2652 genFunction (iCode * ic)
2653 {
2654   symbol *sym;
2655   sym_link *ftype;
2656   bool   switchedPSW = FALSE;
2657
2658   D (emitcode (";", "genFunction "););
2659
2660   _G.nRegsSaved = 0;
2661   /* create the function header */
2662   emitcode (";", "-----------------------------------------");
2663   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2664   emitcode (";", "-----------------------------------------");
2665
2666   emitcode ("", "%s:", sym->rname);
2667   ftype = operandType (IC_LEFT (ic));
2668
2669   if (IFFUNC_ISNAKED(ftype))
2670   {
2671       emitcode(";", "naked function: no prologue.");
2672       return;
2673   }
2674   
2675   if (options.stack_probe) 
2676       emitcode ("lcall","__stack_probe");
2677   /* if critical function then turn interrupts off */
2678   if (IFFUNC_ISCRITICAL (ftype))
2679     emitcode ("clr", "ea");
2680
2681   /* here we need to generate the equates for the
2682      register bank if required */
2683   if (FUNC_REGBANK (ftype) != rbank)
2684     {
2685       int i;
2686
2687       rbank = FUNC_REGBANK (ftype);
2688       for (i = 0; i < ds390_nRegs; i++)
2689         {
2690           if (regs390[i].print) {
2691               if (strcmp (regs390[i].base, "0") == 0)
2692                   emitcode ("", "%s !equ !constbyte",
2693                             regs390[i].dname,
2694                             8 * rbank + regs390[i].offset);
2695               else
2696                   emitcode ("", "%s !equ %s + !constbyte",
2697                             regs390[i].dname,
2698                             regs390[i].base,
2699                             8 * rbank + regs390[i].offset);
2700           }
2701         }
2702     }
2703
2704   /* if this is an interrupt service routine then
2705      save acc, b, dpl, dph  */
2706   if (IFFUNC_ISISR (sym->type))
2707     {
2708
2709       if (!inExcludeList ("acc"))
2710         emitcode ("push", "acc");
2711       if (!inExcludeList ("b"))
2712         emitcode ("push", "b");
2713       if (!inExcludeList ("dpl"))
2714         emitcode ("push", "dpl");
2715       if (!inExcludeList ("dph"))
2716         emitcode ("push", "dph");
2717       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2718         {
2719           emitcode ("push", "dpx");
2720           /* Make sure we're using standard DPTR */
2721           emitcode ("push", "dps");
2722           emitcode ("mov", "dps,#0");
2723           if (options.stack10bit)
2724             {
2725               /* This ISR could conceivably use DPTR2. Better save it. */
2726               emitcode ("push", "dpl1");
2727               emitcode ("push", "dph1");
2728               emitcode ("push", "dpx1");
2729               emitcode ("push",  DP2_RESULT_REG);
2730             }
2731         }
2732       /* if this isr has no bank i.e. is going to
2733          run with bank 0 , then we need to save more
2734          registers :-) */
2735       if (!FUNC_REGBANK (sym->type))
2736         {
2737
2738           /* if this function does not call any other
2739              function then we can be economical and
2740              save only those registers that are used */
2741           if (!IFFUNC_HASFCALL(sym->type))
2742             {
2743               int i;
2744
2745               /* if any registers used */
2746               if (sym->regsUsed)
2747                 {
2748                   /* save the registers used */
2749                   for (i = 0; i < sym->regsUsed->size; i++)
2750                     {
2751                       if (bitVectBitValue (sym->regsUsed, i) ||
2752                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2753                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2754                     }
2755                 }
2756
2757             }
2758           else
2759             {
2760               /* this function has  a function call cannot
2761                  determines register usage so we will have to push the
2762                  entire bank */
2763               saveRBank (0, ic, FALSE);
2764             }
2765         }
2766         else
2767         {
2768             /* This ISR uses a non-zero bank.
2769              *
2770              * We assume that the bank is available for our
2771              * exclusive use.
2772              *
2773              * However, if this ISR calls a function which uses some
2774              * other bank, we must save that bank entirely.
2775              */
2776             unsigned long banksToSave = 0;
2777             
2778             if (IFFUNC_HASFCALL(sym->type))
2779             {
2780
2781 #define MAX_REGISTER_BANKS 4
2782
2783                 iCode *i;
2784                 int ix;
2785
2786                 for (i = ic; i; i = i->next)
2787                 {
2788                     if (i->op == ENDFUNCTION)
2789                     {
2790                         /* we got to the end OK. */
2791                         break;
2792                     }
2793                     
2794                     if (i->op == CALL)
2795                     {
2796                         sym_link *dtype;
2797                         
2798                         dtype = operandType (IC_LEFT(i));
2799                         if (dtype 
2800                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2801                         {
2802                              /* Mark this bank for saving. */
2803                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2804                              {
2805                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2806                              }
2807                              else
2808                              {
2809                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2810                              }
2811                              
2812                              /* And note that we don't need to do it in 
2813                               * genCall.
2814                               */
2815                              i->bankSaved = 1;
2816                         }
2817                     }
2818                     if (i->op == PCALL)
2819                     {
2820                         /* This is a mess; we have no idea what
2821                          * register bank the called function might
2822                          * use.
2823                          *
2824                          * The only thing I can think of to do is
2825                          * throw a warning and hope.
2826                          */
2827                         werror(W_FUNCPTR_IN_USING_ISR);   
2828                     }
2829                 }
2830
2831                 if (banksToSave && options.useXstack)
2832                 {
2833                     /* Since we aren't passing it an ic, 
2834                      * saveRBank will assume r0 is available to abuse.
2835                      *
2836                      * So switch to our (trashable) bank now, so
2837                      * the caller's R0 isn't trashed.
2838                      */
2839                     emitcode ("push", "psw");
2840                     emitcode ("mov", "psw,#!constbyte", 
2841                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2842                     switchedPSW = TRUE;
2843                 }
2844                 
2845                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2846                 {
2847                      if (banksToSave & (1 << ix))
2848                      {
2849                          saveRBank(ix, NULL, FALSE);
2850                      }
2851                 }
2852             }
2853             // jwk: this needs a closer look
2854             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2855         }
2856     }
2857   else
2858     {
2859       /* if callee-save to be used for this function
2860          then save the registers being used in this function */
2861       if (IFFUNC_CALLEESAVES(sym->type))
2862         {
2863           int i;
2864
2865           /* if any registers used */
2866           if (sym->regsUsed)
2867             {
2868               /* save the registers used */
2869               for (i = 0; i < sym->regsUsed->size; i++)
2870                 {
2871                   if (bitVectBitValue (sym->regsUsed, i) ||
2872                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2873                     {
2874                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2875                       _G.nRegsSaved++;
2876                     }
2877                 }
2878             }
2879         }
2880     }
2881
2882   /* set the register bank to the desired value */
2883   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2884    && !switchedPSW)
2885     {
2886       emitcode ("push", "psw");
2887       emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2888     }
2889
2890   if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2891        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2892       if (options.stack10bit) {
2893           emitcode ("push","_bpx");
2894           emitcode ("push","_bpx+1");
2895           emitcode ("mov","_bpx,%s",spname);
2896           emitcode ("mov","_bpx+1,esp");
2897           emitcode ("anl","_bpx+1,#3");
2898       } else {
2899           if (options.useXstack) {
2900               emitcode ("mov", "r0,%s", spname);
2901               emitcode ("mov", "a,_bp");
2902               emitcode ("movx", "@r0,a");
2903               emitcode ("inc", "%s", spname);
2904           } else {
2905               /* set up the stack */
2906               emitcode ("push", "_bp"); /* save the callers stack  */
2907           }
2908           emitcode ("mov", "_bp,%s", spname);
2909       }
2910   }
2911
2912   /* adjust the stack for the function */
2913   if (sym->stack) {
2914       int i = sym->stack;
2915       if (options.stack10bit) {
2916           if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
2917           assert (sym->recvSize <= 4);
2918           emitcode ("mov","a,sp");
2919           emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
2920           emitcode ("mov","sp,a");
2921           emitcode ("mov","a,esp");
2922           emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
2923           emitcode ("mov","esp,a");
2924       } else {
2925           if (i > 256)
2926               werror (W_STACK_OVERFLOW, sym->name);
2927           
2928           if (i > 3 && sym->recvSize < 4) {
2929               
2930               emitcode ("mov", "a,sp");
2931               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
2932               emitcode ("mov", "sp,a");
2933               
2934           } else
2935               while (i--)
2936                   emitcode ("inc", "sp");
2937       }
2938   }
2939
2940   if (sym->xstack)
2941     {
2942
2943       emitcode ("mov", "a,_spx");
2944       emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
2945       emitcode ("mov", "_spx,a");
2946     }
2947
2948 }
2949
2950 /*-----------------------------------------------------------------*/
2951 /* genEndFunction - generates epilogue for functions               */
2952 /*-----------------------------------------------------------------*/
2953 static void
2954 genEndFunction (iCode * ic)
2955 {
2956   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2957
2958   D (emitcode (";", "genEndFunction "););
2959
2960   if (IFFUNC_ISNAKED(sym->type))
2961   {
2962       emitcode(";", "naked function: no epilogue.");
2963       return;
2964   }
2965
2966   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2967        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2968
2969       if (options.stack10bit) {
2970           emitcode ("mov", "sp,_bpx", spname);
2971           emitcode ("mov", "esp,_bpx+1", spname);
2972       } else {
2973           emitcode ("mov", "%s,_bp", spname);
2974       }
2975   }
2976
2977   /* if use external stack but some variables were
2978      added to the local stack then decrement the
2979      local stack */
2980   if (options.useXstack && sym->stack) {
2981       emitcode ("mov", "a,sp");
2982       emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
2983       emitcode ("mov", "sp,a");
2984   }
2985
2986
2987   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
2988        (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
2989
2990       if (options.useXstack) {
2991           emitcode ("mov", "r0,%s", spname);
2992           emitcode ("movx", "a,@r0");
2993           emitcode ("mov", "_bp,a");
2994           emitcode ("dec", "%s", spname);
2995       } else {
2996           if (options.stack10bit) {
2997               emitcode ("pop", "_bpx+1");
2998               emitcode ("pop", "_bpx");
2999           } else {
3000               emitcode ("pop", "_bp");
3001           }
3002       }
3003   }
3004
3005   /* restore the register bank  */
3006   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3007   {
3008     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3009      || !options.useXstack)
3010     {
3011         /* Special case of ISR using non-zero bank with useXstack
3012          * is handled below.
3013          */
3014         emitcode ("pop", "psw");
3015     }
3016   }
3017
3018   if (IFFUNC_ISISR (sym->type))
3019     {
3020
3021       /* now we need to restore the registers */
3022       /* if this isr has no bank i.e. is going to
3023          run with bank 0 , then we need to save more
3024          registers :-) */
3025       if (!FUNC_REGBANK (sym->type))
3026         {
3027           /* if this function does not call any other
3028              function then we can be economical and
3029              save only those registers that are used */
3030           if (!IFFUNC_HASFCALL(sym->type))
3031             {
3032               int i;
3033
3034               /* if any registers used */
3035               if (sym->regsUsed)
3036                 {
3037                   /* save the registers used */
3038                   for (i = sym->regsUsed->size; i >= 0; i--)
3039                     {
3040                       if (bitVectBitValue (sym->regsUsed, i) ||
3041                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3042                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3043                     }
3044                 }
3045
3046             }
3047           else
3048             {
3049               /* this function has  a function call cannot
3050                  determines register usage so we will have to pop the
3051                  entire bank */
3052               unsaveRBank (0, ic, FALSE);
3053             }
3054         }
3055         else
3056         {
3057             /* This ISR uses a non-zero bank.
3058              *
3059              * Restore any register banks saved by genFunction
3060              * in reverse order.
3061              */
3062           // jwk: this needs a closer look
3063             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3064             int ix;
3065           
3066             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3067             {
3068                 if (savedBanks & (1 << ix))
3069                 {
3070                     unsaveRBank(ix, NULL, FALSE);
3071                 }
3072             }
3073             
3074             if (options.useXstack)
3075             {
3076                 /* Restore bank AFTER calling unsaveRBank,
3077                  * since it can trash r0.
3078                  */
3079                 emitcode ("pop", "psw");
3080             }
3081         }
3082
3083       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3084         {
3085           if (options.stack10bit)
3086             {
3087               emitcode ("pop", DP2_RESULT_REG);
3088               emitcode ("pop", "dpx1");
3089               emitcode ("pop", "dph1");
3090               emitcode ("pop", "dpl1");
3091             }
3092           emitcode ("pop", "dps");
3093           emitcode ("pop", "dpx");
3094         }
3095       if (!inExcludeList ("dph"))
3096         emitcode ("pop", "dph");
3097       if (!inExcludeList ("dpl"))
3098         emitcode ("pop", "dpl");
3099       if (!inExcludeList ("b"))
3100         emitcode ("pop", "b");
3101       if (!inExcludeList ("acc"))
3102         emitcode ("pop", "acc");
3103
3104       if (IFFUNC_ISCRITICAL (sym->type))
3105         emitcode ("setb", "ea");
3106
3107       /* if debug then send end of function */
3108       if (options.debug && currFunc) {
3109           _G.debugLine = 1;
3110           emitcode ("", "C$%s$%d$%d$%d ==.",
3111                     FileBaseName (ic->filename), currFunc->lastLine,
3112                     ic->level, ic->block);
3113           if (IS_STATIC (currFunc->etype))
3114             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3115           else
3116             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3117           _G.debugLine = 0;
3118         }
3119
3120       emitcode ("reti", "");
3121     }
3122   else
3123     {
3124       if (IFFUNC_ISCRITICAL (sym->type))
3125         emitcode ("setb", "ea");
3126
3127       if (IFFUNC_CALLEESAVES(sym->type))
3128         {
3129           int i;
3130
3131           /* if any registers used */
3132           if (sym->regsUsed)
3133             {
3134               /* save the registers used */
3135               for (i = sym->regsUsed->size; i >= 0; i--)
3136                 {
3137                   if (bitVectBitValue (sym->regsUsed, i) ||
3138                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3139                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3140                 }
3141             }
3142
3143         }
3144
3145       /* if debug then send end of function */
3146       if (options.debug && currFunc)
3147         {
3148           _G.debugLine = 1;
3149           emitcode ("", "C$%s$%d$%d$%d ==.",
3150                     FileBaseName (ic->filename), currFunc->lastLine,
3151                     ic->level, ic->block);
3152           if (IS_STATIC (currFunc->etype))
3153             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3154           else
3155             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3156           _G.debugLine = 0;
3157         }
3158
3159       emitcode ("ret", "");
3160     }
3161
3162 }
3163
3164 /*-----------------------------------------------------------------*/
3165 /* genJavaNativeRet - generate code for return JavaNative          */
3166 /*-----------------------------------------------------------------*/
3167 static void genJavaNativeRet(iCode *ic)
3168 {
3169     int i, size;
3170
3171     aopOp (IC_LEFT (ic), ic, FALSE, 
3172            (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3173     size = AOP_SIZE (IC_LEFT (ic));
3174
3175     assert (size <= 4);
3176
3177     /* it is assigned to GPR0-R3 then push them */
3178     if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3179         aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3180         for (i = 0 ; i < size ; i++ ) {
3181             emitcode ("push","%s",aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));     
3182         }
3183         for (i = (size-1) ; i >= 0 ; i--) {
3184             emitcode ("pop","a%s",javaRet[i]);
3185         }
3186     } else {
3187         for (i = 0 ; i < size ; i++) 
3188             emitcode ("mov","%s,%s",javaRet[i],aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,FALSE));
3189     }
3190     for (i = size ; i < 4 ; i++ )
3191             emitcode ("mov","%s,#0",javaRet[i]);
3192     return;
3193 }
3194
3195 /*-----------------------------------------------------------------*/
3196 /* genRet - generate code for return statement                     */
3197 /*-----------------------------------------------------------------*/
3198 static void
3199 genRet (iCode * ic)
3200 {
3201   int size, offset = 0, pushed = 0;
3202
3203   D (emitcode (";", "genRet ");
3204     );
3205
3206   /* if we have no return value then
3207      just generate the "ret" */
3208   if (!IC_LEFT (ic))
3209     goto jumpret;
3210
3211   /* if this is a JavaNative function then return 
3212      value in different register */
3213   if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3214       genJavaNativeRet(ic);
3215       goto jumpret;
3216   }
3217   /* we have something to return then
3218      move the return value into place */
3219   aopOp (IC_LEFT (ic), ic, FALSE, 
3220          (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE));
3221   size = AOP_SIZE (IC_LEFT (ic));
3222
3223   _startLazyDPSEvaluation ();
3224   while (size--)
3225     {
3226       char *l;
3227       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3228         {
3229           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3230                       FALSE, TRUE, FALSE);
3231           emitcode ("push", "%s", l);
3232           pushed++;
3233         }
3234       else
3235         {
3236           /* Since A is the last element of fReturn,
3237            * is is OK to clobber it in the aopGet.
3238            */
3239           l = aopGet (AOP (IC_LEFT (ic)), offset,
3240                       FALSE, FALSE, TRUE);
3241           if (strcmp (fReturn[offset], l))
3242             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3243         }
3244     }
3245   _endLazyDPSEvaluation ();
3246
3247   if (pushed)
3248     {
3249       while (pushed)
3250         {
3251           pushed--;
3252           if (strcmp (fReturn[pushed], "a"))
3253             emitcode ("pop", fReturn[pushed]);
3254           else
3255             emitcode ("pop", "acc");
3256         }
3257     }
3258   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3259
3260 jumpret:
3261   /* generate a jump to the return label
3262      if the next is not the return statement */
3263   if (!(ic->next && ic->next->op == LABEL &&
3264         IC_LABEL (ic->next) == returnLabel))
3265
3266     emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3267
3268 }
3269
3270 /*-----------------------------------------------------------------*/
3271 /* genLabel - generates a label                                    */
3272 /*-----------------------------------------------------------------*/
3273 static void
3274 genLabel (iCode * ic)
3275 {
3276   /* special case never generate */
3277   if (IC_LABEL (ic) == entryLabel)
3278     return;
3279
3280   D (emitcode (";", "genLabel ");
3281     );
3282
3283   emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3284 }
3285
3286 /*-----------------------------------------------------------------*/
3287 /* genGoto - generates a ljmp                                      */
3288 /*-----------------------------------------------------------------*/
3289 static void
3290 genGoto (iCode * ic)
3291 {
3292   D (emitcode (";", "genGoto ");
3293     );
3294   emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3295 }
3296
3297 /*-----------------------------------------------------------------*/
3298 /* findLabelBackwards: walks back through the iCode chain looking  */
3299 /* for the given label. Returns number of iCode instructions     */
3300 /* between that label and given ic.          */
3301 /* Returns zero if label not found.          */
3302 /*-----------------------------------------------------------------*/
3303 static int
3304 findLabelBackwards (iCode * ic, int key)
3305 {
3306   int count = 0;
3307
3308   while (ic->prev)
3309     {
3310       ic = ic->prev;
3311       count++;
3312
3313       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3314         {
3315           /* printf("findLabelBackwards = %d\n", count); */
3316           return count;
3317         }
3318     }
3319
3320   return 0;
3321 }
3322
3323 /*-----------------------------------------------------------------*/
3324 /* genPlusIncr :- does addition with increment if possible         */
3325 /*-----------------------------------------------------------------*/
3326 static bool
3327 genPlusIncr (iCode * ic)
3328 {
3329   unsigned int icount;
3330   unsigned int size = getDataSize (IC_RESULT (ic));
3331
3332   /* will try to generate an increment */
3333   /* if the right side is not a literal
3334      we cannot */
3335   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3336     return FALSE;
3337
3338   /* if the literal value of the right hand side
3339      is greater than 4 then it is not worth it */
3340   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3341     return FALSE;
3342
3343   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3344       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3345       while (icount--) {
3346           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3347       }
3348       return TRUE;
3349   }
3350   /* if increment 16 bits in register */
3351   if (
3352        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3353        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3354        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3355        (size > 1) &&
3356        (icount == 1))
3357     {
3358       symbol *tlbl;
3359       int emitTlbl;
3360       int labelRange;
3361
3362       /* If the next instruction is a goto and the goto target
3363        * is <= 5 instructions previous to this, we can generate
3364        * jumps straight to that target.
3365        */
3366       if (ic->next && ic->next->op == GOTO
3367           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3368           && labelRange <= 5)
3369         {
3370           emitcode (";", "tail increment optimized (range %d)", labelRange);
3371           tlbl = IC_LABEL (ic->next);
3372           emitTlbl = 0;
3373         }
3374       else
3375         {
3376           tlbl = newiTempLabel (NULL);
3377           emitTlbl = 1;
3378         }
3379       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3380       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3381           IS_AOP_PREG (IC_RESULT (ic)))
3382         emitcode ("cjne", "%s,#0,!tlabel"
3383                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3384                   ,tlbl->key + 100);
3385       else
3386         {
3387           emitcode ("clr", "a");
3388           emitcode ("cjne", "a,%s,!tlabel"
3389                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3390                     ,tlbl->key + 100);
3391         }
3392
3393       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3394       if (size > 2)
3395         {
3396           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3397               IS_AOP_PREG (IC_RESULT (ic)))
3398             emitcode ("cjne", "%s,#0,!tlabel"
3399                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3400                       ,tlbl->key + 100);
3401           else
3402             emitcode ("cjne", "a,%s,!tlabel"
3403                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3404                       ,tlbl->key + 100);
3405
3406           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3407         }
3408       if (size > 3)
3409         {
3410           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3411               IS_AOP_PREG (IC_RESULT (ic)))
3412             emitcode ("cjne", "%s,#0,!tlabel"
3413                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3414                       ,tlbl->key + 100);
3415           else
3416             {
3417               emitcode ("cjne", "a,%s,!tlabel"
3418                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3419                         ,tlbl->key + 100);
3420             }
3421           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3422         }
3423
3424       if (emitTlbl)
3425         {
3426           emitcode ("", "!tlabeldef", tlbl->key + 100);
3427         }
3428       return TRUE;
3429     }
3430
3431   /* if the sizes are greater than 1 then we cannot */
3432   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3433       AOP_SIZE (IC_LEFT (ic)) > 1)
3434     return FALSE;
3435
3436   /* we can if the aops of the left & result match or
3437      if they are in registers and the registers are the
3438      same */
3439   if (
3440        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3441        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3442        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3443     {
3444
3445       if (icount > 3)
3446         {
3447           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3448           emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3449           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3450         }
3451       else
3452         {
3453
3454           _startLazyDPSEvaluation ();
3455           while (icount--)
3456             {
3457               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3458             }
3459           _endLazyDPSEvaluation ();
3460         }
3461
3462       return TRUE;
3463     }
3464
3465   return FALSE;
3466 }
3467
3468 /*-----------------------------------------------------------------*/
3469 /* outBitAcc - output a bit in acc                                 */
3470 /*-----------------------------------------------------------------*/
3471 static void
3472 outBitAcc (operand * result)
3473 {
3474   symbol *tlbl = newiTempLabel (NULL);
3475   /* if the result is a bit */
3476   if (AOP_TYPE (result) == AOP_CRY)
3477     {
3478       aopPut (AOP (result), "a", 0);
3479     }
3480   else
3481     {
3482       emitcode ("jz", "!tlabel", tlbl->key + 100);
3483       emitcode ("mov", "a,%s", one);
3484       emitcode ("", "!tlabeldef", tlbl->key + 100);
3485       outAcc (result);
3486     }
3487 }
3488
3489 /*-----------------------------------------------------------------*/
3490 /* genPlusBits - generates code for addition of two bits           */
3491 /*-----------------------------------------------------------------*/
3492 static void
3493 genPlusBits (iCode * ic)
3494 {
3495   D (emitcode (";", "genPlusBits ");
3496     );
3497   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3498     {
3499       symbol *lbl = newiTempLabel (NULL);
3500       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3501       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3502       emitcode ("cpl", "c");
3503       emitcode ("", "!tlabeldef", (lbl->key + 100));
3504       outBitC (IC_RESULT (ic));
3505     }
3506   else
3507     {
3508       emitcode ("clr", "a");
3509       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3510       emitcode ("rlc", "a");
3511       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3512       emitcode ("addc", "a,#0");
3513       outAcc (IC_RESULT (ic));
3514     }
3515 }
3516
3517 static void
3518 adjustArithmeticResult (iCode * ic)
3519 {
3520   if (opIsGptr (IC_RESULT (ic)) &&
3521       opIsGptr (IC_LEFT (ic)) &&
3522       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3523     {
3524       aopPut (AOP (IC_RESULT (ic)),
3525               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3526               GPTRSIZE - 1);
3527     }
3528
3529   if (opIsGptr (IC_RESULT (ic)) &&
3530       opIsGptr (IC_RIGHT (ic)) &&
3531       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3532     {
3533       aopPut (AOP (IC_RESULT (ic)),
3534             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3535               GPTRSIZE - 1);
3536     }
3537
3538   if (opIsGptr (IC_RESULT (ic)) &&
3539       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3540       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3541       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3542       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3543     {
3544       char buffer[5];
3545       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3546       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3547     }
3548 }
3549
3550 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3551       // Please don't bring it back without a really good reason.
3552 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3553 // (because all three operands are in far space).
3554 #define AOP_OP_3(ic) \
3555     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3556     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3557     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3558               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3559     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3560         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3561     { \
3562         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3563         fprintf(stderr,                                  \
3564                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3565     }
3566 #endif
3567
3568 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3569 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3570 // will be set TRUE. The caller must then handle the case specially, noting
3571 // that the IC_RESULT operand is not aopOp'd.
3572 #define AOP_OP_3_NOFATAL(ic, rc) \
3573     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3574     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \
3575                                   ((OP_SYMBOL(IC_RESULT(ic))->ruonly) && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))); \
3576     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3577         (isOperandInFarSpace(IC_RESULT(ic)) || (OP_SYMBOL(IC_RESULT(ic))->ruonly && !isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))))) \
3578     { \
3579        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3580        rc = TRUE; \
3581     }  \
3582     else \
3583     { \
3584        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3585                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3586        rc = FALSE; \
3587        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3588            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3589        { \
3590             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3591             fprintf(stderr,                                  \
3592                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3593        } \
3594     }
3595
3596 // aopOp the left & right operands of an ic.
3597 #define AOP_OP_2(ic) \
3598     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3599     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3600
3601 // convienience macro.
3602 #define AOP_SET_LOCALS(ic) \
3603     left = IC_LEFT(ic); \
3604     right = IC_RIGHT(ic); \
3605     result = IC_RESULT(ic);
3606
3607
3608 // Given an integer value of pushedSize bytes on the stack,
3609 // adjust it to be resultSize bytes, either by discarding
3610 // the most significant bytes or by zero-padding.
3611 //
3612 // On exit from this macro, pushedSize will have been adjusted to
3613 // equal resultSize, and ACC may be trashed.
3614 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3615       /* If the pushed data is bigger than the result,          \
3616        * simply discard unused bytes. Icky, but works.          \
3617        */                                                       \
3618       while (pushedSize > resultSize)                           \
3619       {                                                         \
3620           D (emitcode (";", "discarding unused result byte."););\
3621           emitcode ("pop", "acc");                              \
3622           pushedSize--;                                         \
3623       }                                                         \
3624       if (pushedSize < resultSize)                              \
3625       {                                                         \
3626           emitcode ("clr", "a");                                \
3627           /* Conversly, we haven't pushed enough here.          \
3628            * just zero-pad, and all is well.                    \
3629            */                                                   \
3630           while (pushedSize < resultSize)                       \
3631           {                                                     \
3632               emitcode("push", "acc");                          \
3633               pushedSize++;                                     \
3634           }                                                     \
3635       }                                                         \
3636       assert(pushedSize == resultSize);
3637
3638 /*-----------------------------------------------------------------*/
3639 /* genPlus - generates code for addition                           */
3640 /*-----------------------------------------------------------------*/
3641 static void
3642 genPlus (iCode * ic)
3643 {
3644   int size, offset = 0;
3645   bool pushResult = FALSE;
3646   int rSize;
3647
3648   D (emitcode (";", "genPlus "););
3649
3650   /* special cases :- */
3651   if ( IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly &&
3652       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
3653       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
3654       size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
3655       if (size <= 9) {
3656           while (size--) emitcode ("inc","dptr");
3657       } else {
3658           emitcode ("mov","a,dpl");
3659           emitcode ("add","a,#!constbyte",size & 0xff);
3660           emitcode ("mov","dpl,a");
3661           emitcode ("mov","a,dph");
3662           emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
3663           emitcode ("mov","dph,a");
3664           emitcode ("mov","a,dpx");
3665           emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
3666           emitcode ("mov","dpx,a");
3667       }
3668       freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
3669       return ;
3670   }
3671   if ( IS_SYMOP(IC_LEFT(ic)) && 
3672        OP_SYMBOL(IC_LEFT(ic))->remat &&
3673        isOperandInFarSpace(IC_RIGHT(ic))) {
3674       operand *op = IC_RIGHT(ic);
3675       IC_RIGHT(ic) = IC_LEFT(ic);
3676       IC_LEFT(ic) = op;
3677   }
3678                 
3679   AOP_OP_3_NOFATAL (ic, pushResult);
3680   if (pushResult)
3681     {
3682       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3683     }
3684
3685   if (!pushResult)
3686     {
3687       /* if literal, literal on the right or
3688          if left requires ACC or right is already
3689          in ACC */
3690       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3691        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3692           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3693         {
3694           operand *t = IC_RIGHT (ic);
3695           IC_RIGHT (ic) = IC_LEFT (ic);
3696           IC_LEFT (ic) = t;
3697           emitcode (";", "Swapped plus args.");
3698         }
3699
3700       /* if both left & right are in bit
3701          space */
3702       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3703           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3704         {
3705           genPlusBits (ic);
3706           goto release;
3707         }
3708
3709       /* if left in bit space & right literal */
3710       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3711           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3712         {
3713           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3714           /* if result in bit space */
3715           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3716             {
3717               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3718                 emitcode ("cpl", "c");
3719               outBitC (IC_RESULT (ic));
3720             }
3721           else
3722             {
3723               size = getDataSize (IC_RESULT (ic));
3724               _startLazyDPSEvaluation ();
3725               while (size--)
3726                 {
3727                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3728                   emitcode ("addc", "a,#0");
3729                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3730                 }
3731               _endLazyDPSEvaluation ();
3732             }
3733           goto release;
3734         }
3735
3736       /* if I can do an increment instead
3737          of add then GOOD for ME */
3738       if (genPlusIncr (ic) == TRUE)
3739         {
3740           emitcode (";", "did genPlusIncr");
3741           goto release;
3742         }
3743
3744     }
3745   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3746
3747   _startLazyDPSEvaluation ();
3748   while (size--)
3749     {
3750       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3751         {
3752           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3753           if (offset == 0)
3754             emitcode ("add", "a,%s",
3755                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3756           else
3757             emitcode ("addc", "a,%s",
3758                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3759         }
3760       else
3761         {
3762           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3763           {
3764               /* right is going to use ACC or we would have taken the
3765                * above branch.
3766                */
3767               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3768        TR_AP("#3");
3769               D(emitcode(";", "+ AOP_ACC special case."););
3770               emitcode("xch", "a, %s", DP2_RESULT_REG);
3771           }
3772           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3773           if (offset == 0)
3774           {
3775             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3776             {
3777          TR_AP("#4");
3778                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3779             }
3780             else
3781             {
3782                 emitcode ("add", "a,%s",
3783                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3784             }
3785           }
3786           else
3787           {
3788             emitcode ("addc", "a,%s",
3789                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3790           }
3791         }
3792       if (!pushResult)
3793         {
3794           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3795         }
3796       else
3797         {
3798           emitcode ("push", "acc");
3799         }
3800       offset++;
3801     }
3802   _endLazyDPSEvaluation ();
3803
3804   if (pushResult)
3805     {
3806       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3807
3808       size = getDataSize (IC_LEFT (ic));
3809       rSize = getDataSize (IC_RESULT (ic));
3810
3811       ADJUST_PUSHED_RESULT(size, rSize);
3812
3813       _startLazyDPSEvaluation ();
3814       while (size--)
3815         {
3816           emitcode ("pop", "acc");
3817           aopPut (AOP (IC_RESULT (ic)), "a", size);
3818         }
3819       _endLazyDPSEvaluation ();
3820     }
3821
3822   adjustArithmeticResult (ic);
3823
3824 release:
3825   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3826   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3827   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3828 }
3829
3830 /*-----------------------------------------------------------------*/
3831 /* genMinusDec :- does subtraction with deccrement if possible     */
3832 /*-----------------------------------------------------------------*/
3833 static bool
3834 genMinusDec (iCode * ic)
3835 {
3836   unsigned int icount;
3837   unsigned int size = getDataSize (IC_RESULT (ic));
3838
3839   /* will try to generate an increment */
3840   /* if the right side is not a literal
3841      we cannot */
3842   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3843     return FALSE;
3844
3845   /* if the literal value of the right hand side
3846      is greater than 4 then it is not worth it */
3847   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3848     return FALSE;
3849
3850   if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3851       AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3852       while (icount--) {
3853           emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,FALSE));
3854       }
3855       return TRUE;
3856   }
3857   /* if decrement 16 bits in register */
3858   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3859       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3860       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3861       (size > 1) &&
3862       (icount == 1))
3863     {
3864       symbol *tlbl;
3865       int emitTlbl;
3866       int labelRange;
3867
3868       /* If the next instruction is a goto and the goto target
3869          * is <= 5 instructions previous to this, we can generate
3870          * jumps straight to that target.
3871        */
3872       if (ic->next && ic->next->op == GOTO
3873           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3874           && labelRange <= 5)
3875         {
3876           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3877           tlbl = IC_LABEL (ic->next);
3878           emitTlbl = 0;
3879         }
3880       else
3881         {
3882           tlbl = newiTempLabel (NULL);
3883           emitTlbl = 1;
3884         }
3885
3886       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3887       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3888           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3889           IS_AOP_PREG (IC_RESULT (ic)))
3890         emitcode ("cjne", "%s,#!constbyte,!tlabel"
3891                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE), 0xff
3892                   ,tlbl->key + 100);
3893       else
3894         {
3895           emitcode ("mov", "a,#!constbyte",0xff);
3896           emitcode ("cjne", "a,%s,!tlabel"
3897                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3898                     ,tlbl->key + 100);
3899         }
3900       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3901       if (size > 2)
3902         {
3903           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3904               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3905               IS_AOP_PREG (IC_RESULT (ic)))
3906             emitcode ("cjne", "%s,#!constbyte,!tlabel"
3907                       ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE),0xff
3908                       ,tlbl->key + 100);
3909           else
3910             {
3911               emitcode ("cjne", "a,%s,!tlabel"
3912                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3913                         ,tlbl->key + 100);
3914             }
3915           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3916         }
3917       if (size > 3)
3918         {
3919           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3920               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3921               IS_AOP_PREG (IC_RESULT (ic)))
3922             emitcode ("cjne", "%s,#!constbyte,!tlabel"
3923                       ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE),0xff
3924                       ,tlbl->key + 100);
3925           else
3926             {
3927               emitcode ("cjne", "a,%s,!tlabel"
3928                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3929                         ,tlbl->key + 100);
3930             }
3931           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3932         }
3933       if (emitTlbl)
3934         {
3935           emitcode ("", "!tlabeldef", tlbl->key + 100);
3936         }
3937       return TRUE;
3938     }
3939
3940   /* if the sizes are greater than 1 then we cannot */
3941   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3942       AOP_SIZE (IC_LEFT (ic)) > 1)
3943     return FALSE;
3944
3945   /* we can if the aops of the left & result match or
3946      if they are in registers and the registers are the
3947      same */
3948   if (
3949        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3950        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3951        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3952     {
3953
3954       _startLazyDPSEvaluation ();
3955       while (icount--)
3956         {
3957           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3958         }
3959       _endLazyDPSEvaluation ();
3960
3961       return TRUE;
3962     }
3963
3964   return FALSE;
3965 }
3966
3967 /*-----------------------------------------------------------------*/
3968 /* addSign - complete with sign                                    */
3969 /*-----------------------------------------------------------------*/
3970 static void
3971 addSign (operand * result, int offset, int sign)
3972 {
3973   int size = (getDataSize (result) - offset);
3974   if (size > 0)
3975     {
3976       _startLazyDPSEvaluation();
3977       if (sign)
3978         {
3979           emitcode ("rlc", "a");
3980           emitcode ("subb", "a,acc");
3981           while (size--)
3982           {
3983             aopPut (AOP (result), "a", offset++);
3984           }
3985         }
3986       else
3987       {
3988         while (size--)
3989         {
3990           aopPut (AOP (result), zero, offset++);
3991         }
3992       }
3993       _endLazyDPSEvaluation();
3994     }
3995 }
3996
3997 /*-----------------------------------------------------------------*/
3998 /* genMinusBits - generates code for subtraction  of two bits      */
3999 /*-----------------------------------------------------------------*/
4000 static void
4001 genMinusBits (iCode * ic)
4002 {
4003   symbol *lbl = newiTempLabel (NULL);
4004
4005   D (emitcode (";", "genMinusBits "););
4006
4007   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4008     {
4009       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4010       emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4011       emitcode ("cpl", "c");
4012       emitcode ("", "!tlabeldef", (lbl->key + 100));
4013       outBitC (IC_RESULT (ic));
4014     }
4015   else
4016     {
4017       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4018       emitcode ("subb", "a,acc");
4019       emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4020       emitcode ("inc", "a");
4021       emitcode ("", "!tlabeldef", (lbl->key + 100));
4022       aopPut (AOP (IC_RESULT (ic)), "a", 0);
4023       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4024     }
4025 }
4026
4027 /*-----------------------------------------------------------------*/
4028 /* genMinus - generates code for subtraction                       */
4029 /*-----------------------------------------------------------------*/
4030 static void
4031 genMinus (iCode * ic)
4032 {
4033   int size, offset = 0;
4034   int rSize;
4035   unsigned long lit = 0L;
4036   bool pushResult = FALSE;
4037
4038   D (emitcode (";", "genMinus "););
4039
4040   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
4041   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
4042   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
4043       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
4044     {
4045       pushResult = TRUE;
4046     }
4047   else
4048     {
4049       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
4050
4051       /* special cases :- */
4052       /* if both left & right are in bit space */
4053       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4054           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4055         {
4056           genMinusBits (ic);
4057           goto release;
4058         }
4059
4060       /* if I can do an decrement instead
4061          of subtract then GOOD for ME */
4062       if (genMinusDec (ic) == TRUE)
4063         goto release;
4064
4065     }
4066
4067   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4068
4069   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4070     {
4071       CLRC;
4072     }
4073   else
4074     {
4075       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4076       lit = -(long) lit;
4077     }
4078
4079
4080   /* if literal, add a,#-lit, else normal subb */
4081   _startLazyDPSEvaluation ();
4082   while (size--)
4083     {
4084       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
4085       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4086         emitcode ("subb", "a,%s",
4087                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
4088       else
4089         {
4090           /* first add without previous c */
4091           if (!offset) {
4092             if (!size && lit==-1) {
4093               emitcode ("dec", "a");
4094             } else {
4095               emitcode ("add", "a,#!constbyte",
4096                         (unsigned int) (lit & 0x0FFL));
4097             }
4098           } else {
4099             emitcode ("addc", "a,#!constbyte",
4100                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4101           }
4102         }
4103
4104       if (pushResult)
4105         {
4106           emitcode ("push", "acc");
4107         }
4108       else
4109         {
4110           aopPut (AOP (IC_RESULT (ic)), "a", offset);
4111         }
4112       offset++;
4113     }
4114   _endLazyDPSEvaluation ();
4115
4116   if (pushResult)
4117     {
4118       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4119
4120       size = getDataSize (IC_LEFT (ic));
4121       rSize = getDataSize (IC_RESULT (ic));
4122
4123       ADJUST_PUSHED_RESULT(size, rSize);
4124
4125       _startLazyDPSEvaluation ();
4126       while (size--)
4127         {
4128           emitcode ("pop", "acc");
4129           aopPut (AOP (IC_RESULT (ic)), "a", size);
4130         }
4131       _endLazyDPSEvaluation ();
4132     }
4133
4134   adjustArithmeticResult (ic);
4135
4136 release:
4137   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4138   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4139   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4140 }
4141
4142
4143 /*-----------------------------------------------------------------*/
4144 /* genMultbits :- multiplication of bits                           */
4145 /*-----------------------------------------------------------------*/
4146 static void
4147 genMultbits (operand * left,
4148              operand * right,
4149              operand * result,
4150              iCode   * ic)
4151 {
4152   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4153   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4154   aopOp(result, ic, TRUE, FALSE);
4155   outBitC (result);
4156 }
4157
4158
4159 /*-----------------------------------------------------------------*/
4160 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
4161 /*-----------------------------------------------------------------*/
4162 static void
4163 genMultOneByte (operand * left,
4164                 operand * right,
4165                 operand * result,
4166                 iCode   * ic)
4167 {
4168   sym_link *opetype = operandType (result);
4169   symbol *lbl;
4170
4171
4172   /* (if two literals: the value is computed before) */
4173   /* if one literal, literal on the right */
4174   if (AOP_TYPE (left) == AOP_LIT)
4175     {
4176       operand *t = right;
4177       right = left;
4178       left = t;
4179       emitcode (";", "swapped left and right");
4180     }
4181
4182   if (SPEC_USIGN(opetype)
4183       // ignore the sign of left and right, what else can we do?
4184       || (SPEC_USIGN(operandType(left)) && 
4185           SPEC_USIGN(operandType(right)))) {
4186     // just an unsigned 8*8=8/16 multiply
4187     //emitcode (";","unsigned");
4188     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4189     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4190     emitcode ("mul", "ab");
4191    
4192     _G.accInUse++; _G.bInUse++;
4193     aopOp(result, ic, TRUE, FALSE);
4194       
4195       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4196       {
4197           // this should never happen
4198           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4199                    AOP_SIZE(result), __FILE__, lineno);
4200           exit (1);
4201       }      
4202       
4203     aopPut (AOP (result), "a", 0);
4204     _G.accInUse--; _G.bInUse--;
4205     if (AOP_SIZE(result)==2) 
4206     {
4207       aopPut (AOP (result), "b", 1);
4208     }
4209     return;
4210   }
4211
4212   // we have to do a signed multiply
4213
4214   emitcode (";", "signed");
4215   emitcode ("clr", "F0"); // reset sign flag
4216   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4217
4218   lbl=newiTempLabel(NULL);
4219   emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
4220   // left side is negative, 8-bit two's complement, this fails for -128
4221   emitcode ("setb", "F0"); // set sign flag
4222   emitcode ("cpl", "a");
4223   emitcode ("inc", "a");
4224
4225   emitcode ("", "!tlabeldef", lbl->key+100);
4226
4227   /* if literal */
4228   if (AOP_TYPE(right)==AOP_LIT) {
4229     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4230     /* AND literal negative */
4231     if ((int) val < 0) {
4232       emitcode ("cpl", "F0"); // complement sign flag
4233       emitcode ("mov", "b,#!constbyte", -val);
4234     } else {
4235       emitcode ("mov", "b,#!constbyte", val);
4236     }
4237   } else {
4238     lbl=newiTempLabel(NULL);
4239     emitcode ("mov", "b,a");
4240     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4241     emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4242     // right side is negative, 8-bit two's complement
4243     emitcode ("cpl", "F0"); // complement sign flag
4244     emitcode ("cpl", "a");
4245     emitcode ("inc", "a");
4246     emitcode ("", "!tlabeldef", lbl->key+100);
4247   }
4248   emitcode ("mul", "ab");
4249     
4250   _G.accInUse++;_G.bInUse++;
4251   aopOp(result, ic, TRUE, FALSE);
4252     
4253   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4254   {
4255     // this should never happen
4256       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4257                AOP_SIZE(result), __FILE__, lineno);
4258       exit (1);
4259   }    
4260     
4261   lbl=newiTempLabel(NULL);
4262   emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4263   // only ONE op was negative, we have to do a 8/16-bit two's complement
4264   emitcode ("cpl", "a"); // lsb
4265   if (AOP_SIZE(result)==1) {
4266     emitcode ("inc", "a");
4267   } else {
4268     emitcode ("add", "a,#1");
4269     emitcode ("xch", "a,b");
4270     emitcode ("cpl", "a"); // msb
4271     emitcode ("addc", "a,#0");
4272     emitcode ("xch", "a,b");
4273   }
4274
4275   emitcode ("", "!tlabeldef", lbl->key+100);
4276   aopPut (AOP (result), "a", 0);
4277   _G.accInUse--;_G.bInUse--;
4278   if (AOP_SIZE(result)==2) {
4279     aopPut (AOP (result), "b", 1);
4280   }
4281 }
4282
4283 /*-----------------------------------------------------------------*/
4284 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4285 /*-----------------------------------------------------------------*/
4286 static void genMultTwoByte (operand *left, operand *right, 
4287                             operand *result, iCode *ic)
4288 {
4289         sym_link *retype = getSpec(operandType(right));
4290         sym_link *letype = getSpec(operandType(left));
4291         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4292         symbol *lbl;
4293
4294         if (AOP_TYPE (left) == AOP_LIT) {
4295                 operand *t = right;
4296                 right = left;
4297                 left = t;
4298         }
4299         /* save EA bit in F1 */
4300         lbl = newiTempLabel(NULL);
4301         emitcode ("setb","F1");
4302         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4303         emitcode ("clr","F1");
4304         emitcode("","!tlabeldef",lbl->key+100);
4305
4306         /* load up MB with right */
4307         if (!umult) {
4308                 emitcode("clr","F0");
4309                 if (AOP_TYPE(right) == AOP_LIT) {
4310                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4311                         if (val < 0) {
4312                                 emitcode("setb","F0");
4313                                 val = -val;
4314                         }
4315                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4316                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4317                 } else {
4318                         lbl = newiTempLabel(NULL);
4319                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4320                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4321                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4322                         emitcode ("xch", "a,b");
4323                         emitcode ("cpl","a");
4324                         emitcode ("add", "a,#1");
4325                         emitcode ("xch", "a,b");
4326                         emitcode ("cpl", "a"); // msb
4327                         emitcode ("addc", "a,#0");
4328                         emitcode ("setb","F0");
4329                         emitcode ("","!tlabeldef",lbl->key+100);
4330                         emitcode ("mov","mb,b");
4331                         emitcode ("mov","mb,a");
4332                 }
4333         } else {
4334                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4335                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4336         }
4337         /* load up MA with left */
4338         if (!umult) {
4339                 lbl = newiTempLabel(NULL);
4340                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4341                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4342                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4343                 emitcode ("xch", "a,b");
4344                 emitcode ("cpl","a");
4345                 emitcode ("add", "a,#1");
4346                 emitcode ("xch", "a,b");
4347                 emitcode ("cpl", "a"); // msb
4348                 emitcode ("addc","a,#0");
4349                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4350                 emitcode ("setb","F0");
4351                 emitcode ("","!tlabeldef",lbl->key+100);
4352                 emitcode ("mov","ma,b");
4353                 emitcode ("mov","ma,a");
4354         } else {
4355                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4356                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4357         }
4358         /* wait for multiplication to finish */
4359         lbl = newiTempLabel(NULL);
4360         emitcode("","!tlabeldef", lbl->key+100);
4361         emitcode("mov","a,mcnt1");
4362         emitcode("anl","a,#!constbyte",0x80);
4363         emitcode("jnz","!tlabel",lbl->key+100);
4364         
4365         freeAsmop (left, NULL, ic, TRUE);
4366         freeAsmop (right, NULL, ic,TRUE);
4367         aopOp(result, ic, TRUE, FALSE);
4368
4369         /* if unsigned then simple */   
4370         if (umult) {
4371                 emitcode ("mov","a,ma");
4372                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4373                 emitcode ("mov","a,ma");
4374                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4375                 aopPut(AOP(result),"ma",1);
4376                 aopPut(AOP(result),"ma",0);
4377         } else {
4378                 emitcode("push","ma");
4379                 emitcode("push","ma");
4380                 emitcode("push","ma");
4381                 MOVA("ma");
4382                 /* negate result if needed */
4383                 lbl = newiTempLabel(NULL);      
4384                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4385                 emitcode("cpl","a");
4386                 emitcode("add","a,#1");
4387                 emitcode("","!tlabeldef", lbl->key+100);
4388                 if (AOP_TYPE(result) == AOP_ACC)
4389                 {
4390                     D(emitcode(";", "ACC special case."););
4391                     /* We know result is the only live aop, and 
4392                      * it's obviously not a DPTR2, so AP is available.
4393                      */
4394                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4395                 }
4396                 else
4397                 {
4398                     aopPut(AOP(result),"a",0);
4399                 }
4400             
4401                 emitcode("pop","acc");
4402                 lbl = newiTempLabel(NULL);      
4403                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4404                 emitcode("cpl","a");
4405                 emitcode("addc","a,#0");
4406                 emitcode("","!tlabeldef", lbl->key+100);
4407                 aopPut(AOP(result),"a",1);
4408                 emitcode("pop","acc");
4409                 if (AOP_SIZE(result) >= 3) {
4410                         lbl = newiTempLabel(NULL);      
4411                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4412                         emitcode("cpl","a");
4413                         emitcode("addc","a,#0");                        
4414                         emitcode("","!tlabeldef", lbl->key+100);
4415                         aopPut(AOP(result),"a",2);
4416                 }
4417                 emitcode("pop","acc");
4418                 if (AOP_SIZE(result) >= 4) {
4419                         lbl = newiTempLabel(NULL);      
4420                         emitcode("jnb","F0,!tlabel",lbl->key+100);
4421                         emitcode("cpl","a");
4422                         emitcode("addc","a,#0");                        
4423                         emitcode("","!tlabeldef", lbl->key+100);
4424                         aopPut(AOP(result),"a",3);
4425                 }
4426                 if (AOP_TYPE(result) == AOP_ACC)
4427                 {
4428                     /* We stashed the result away above. */
4429                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4430                 }           
4431                 
4432         }
4433         freeAsmop (result, NULL, ic, TRUE);
4434
4435         /* restore EA bit in F1 */
4436         lbl = newiTempLabel(NULL);
4437         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4438         emitcode ("setb","EA");
4439         emitcode("","!tlabeldef",lbl->key+100);
4440         return ;
4441 }
4442
4443 /*-----------------------------------------------------------------*/
4444 /* genMult - generates code for multiplication                     */
4445 /*-----------------------------------------------------------------*/
4446 static void
4447 genMult (iCode * ic)
4448 {
4449   operand *left = IC_LEFT (ic);
4450   operand *right = IC_RIGHT (ic);
4451   operand *result = IC_RESULT (ic);
4452
4453   D (emitcode (";", "genMult "););
4454
4455   /* assign the amsops */
4456   AOP_OP_2 (ic);
4457
4458   /* special cases first */
4459   /* both are bits */
4460   if (AOP_TYPE (left) == AOP_CRY &&
4461       AOP_TYPE (right) == AOP_CRY)
4462     {
4463       genMultbits (left, right, result, ic);
4464       goto release;
4465     }
4466
4467   /* if both are of size == 1 */
4468   if (AOP_SIZE (left) == 1 &&
4469       AOP_SIZE (right) == 1)
4470     {
4471       genMultOneByte (left, right, result, ic);
4472       goto release;
4473     }
4474
4475   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4476           /* use the ds390 ARITHMETIC accel UNIT */
4477           genMultTwoByte (left, right, result, ic);
4478           return ;
4479   }
4480   /* should have been converted to function call */
4481   assert (0);
4482
4483 release:
4484   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4485   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4486   freeAsmop (result, NULL, ic, TRUE);
4487 }
4488
4489 /*-----------------------------------------------------------------*/
4490 /* genDivbits :- division of bits                                  */
4491 /*-----------------------------------------------------------------*/
4492 static void
4493 genDivbits (operand * left,
4494             operand * right,
4495             operand * result,
4496             iCode   * ic)
4497 {
4498
4499   char *l;
4500
4501   /* the result must be bit */
4502   LOAD_AB_FOR_DIV (left, right, l);
4503   emitcode ("div", "ab");
4504   emitcode ("rrc", "a");
4505   aopOp(result, ic, TRUE, FALSE);
4506     
4507   aopPut (AOP (result), "c", 0);
4508 }
4509
4510 /*-----------------------------------------------------------------*/
4511 /* genDivOneByte : 8 bit division                                  */
4512 /*-----------------------------------------------------------------*/
4513 static void
4514 genDivOneByte (operand * left,
4515                operand * right,
4516                operand * result,
4517                iCode   * ic)
4518 {
4519   sym_link *opetype = operandType (result);
4520   char *l;
4521   symbol *lbl;
4522   int size, offset;
4523
4524   offset = 1;
4525   /* signed or unsigned */
4526   if (SPEC_USIGN (opetype))
4527     {
4528         /* unsigned is easy */
4529         LOAD_AB_FOR_DIV (left, right, l);
4530         emitcode ("div", "ab");
4531
4532         _G.accInUse++;
4533         aopOp(result, ic, TRUE, FALSE);
4534         aopPut (AOP (result), "a", 0);
4535         _G.accInUse--;
4536
4537         size = AOP_SIZE (result) - 1;
4538         
4539         while (size--)
4540         {
4541             aopPut (AOP (result), zero, offset++);
4542         }
4543       return;
4544     }
4545
4546   /* signed is a little bit more difficult */
4547
4548   /* save the signs of the operands */
4549   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4550   MOVA (l);
4551   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4552   emitcode ("push", "acc");     /* save it on the stack */
4553
4554   /* now sign adjust for both left & right */
4555   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4556   MOVA (l);
4557   lbl = newiTempLabel (NULL);
4558   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4559   emitcode ("cpl", "a");
4560   emitcode ("inc", "a");
4561   emitcode ("", "!tlabeldef", (lbl->key + 100));
4562   emitcode ("mov", "b,a");
4563
4564   /* sign adjust left side */
4565   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4566   MOVA (l);
4567
4568   lbl = newiTempLabel (NULL);
4569   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4570   emitcode ("cpl", "a");
4571   emitcode ("inc", "a");
4572   emitcode ("", "!tlabeldef", (lbl->key + 100));
4573
4574   /* now the division */
4575   emitcode ("nop", "; workaround for DS80C390 div bug.");
4576   emitcode ("div", "ab");
4577   /* we are interested in the lower order
4578      only */
4579   emitcode ("mov", "b,a");
4580   lbl = newiTempLabel (NULL);
4581   emitcode ("pop", "acc");
4582   /* if there was an over flow we don't
4583      adjust the sign of the result */
4584   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4585   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4586   CLRC;
4587   emitcode ("clr", "a");
4588   emitcode ("subb", "a,b");
4589   emitcode ("mov", "b,a");
4590   emitcode ("", "!tlabeldef", (lbl->key + 100));
4591
4592   /* now we are done */
4593   _G.accInUse++;     _G.bInUse++;
4594     aopOp(result, ic, TRUE, FALSE);
4595     
4596     aopPut (AOP (result), "b", 0);
4597     
4598     size = AOP_SIZE (result) - 1;
4599     
4600     if (size > 0)
4601     {
4602       emitcode ("mov", "c,b.7");
4603       emitcode ("subb", "a,acc");
4604     }
4605     while (size--)
4606     {
4607         aopPut (AOP (result), "a", offset++);
4608     }
4609     _G.accInUse--;     _G.bInUse--;
4610
4611 }
4612
4613 /*-----------------------------------------------------------------*/
4614 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4615 /*-----------------------------------------------------------------*/
4616 static void genDivTwoByte (operand *left, operand *right, 
4617                             operand *result, iCode *ic)
4618 {
4619         sym_link *retype = getSpec(operandType(right));
4620         sym_link *letype = getSpec(operandType(left));
4621         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4622         symbol *lbl;
4623
4624         /* save EA bit in F1 */
4625         lbl = newiTempLabel(NULL);
4626         emitcode ("setb","F1");
4627         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4628         emitcode ("clr","F1");
4629         emitcode("","!tlabeldef",lbl->key+100);
4630
4631         /* load up MA with left */
4632         if (!umult) {
4633                 emitcode("clr","F0");
4634                 lbl = newiTempLabel(NULL);
4635                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4636                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4637                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4638                 emitcode ("xch", "a,b");
4639                 emitcode ("cpl","a");
4640                 emitcode ("add", "a,#1");
4641                 emitcode ("xch", "a,b");
4642                 emitcode ("cpl", "a"); // msb
4643                 emitcode ("addc","a,#0");
4644                 emitcode ("setb","F0");
4645                 emitcode ("","!tlabeldef",lbl->key+100);
4646                 emitcode ("mov","ma,b");
4647                 emitcode ("mov","ma,a");
4648         } else {
4649                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4650                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4651         }
4652
4653         /* load up MB with right */
4654         if (!umult) {
4655                 if (AOP_TYPE(right) == AOP_LIT) {
4656                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4657                         if (val < 0) {
4658                                 lbl = newiTempLabel(NULL);
4659                                 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4660                                 emitcode("setb","F0");
4661                                 emitcode ("","!tlabeldef",lbl->key+100);
4662                                 val = -val;
4663                         } 
4664                         emitcode ("mov","mb,#!constbyte",val & 0xff);               
4665                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4666                 } else {
4667                         lbl = newiTempLabel(NULL);
4668                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4669                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4670                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4671                         emitcode ("xch", "a,b");
4672                         emitcode ("cpl","a");
4673                         emitcode ("add", "a,#1");
4674                         emitcode ("xch", "a,b");
4675                         emitcode ("cpl", "a"); // msb
4676                         emitcode ("addc", "a,#0");
4677                         emitcode ("jbc","F0,!tlabel",lbl->key+100);
4678                         emitcode ("setb","F0");
4679                         emitcode ("","!tlabeldef",lbl->key+100);
4680                         emitcode ("mov","mb,b");
4681                         emitcode ("mov","mb,a");
4682                 }
4683         } else {
4684                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4685                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4686         }
4687
4688         /* wait for multiplication to finish */
4689         lbl = newiTempLabel(NULL);
4690         emitcode("","!tlabeldef", lbl->key+100);
4691         emitcode("mov","a,mcnt1");
4692         emitcode("anl","a,#!constbyte",0x80);
4693         emitcode("jnz","!tlabel",lbl->key+100);
4694         
4695         freeAsmop (left, NULL, ic, TRUE);
4696         freeAsmop (right, NULL, ic,TRUE);
4697         aopOp(result, ic, TRUE, FALSE);
4698
4699         /* if unsigned then simple */   
4700         if (umult) {
4701                 aopPut(AOP(result),"ma",1);
4702                 aopPut(AOP(result),"ma",0);
4703         } else {
4704                 emitcode("push","ma");
4705                 MOVA("ma");
4706                 /* negate result if needed */
4707                 lbl = newiTempLabel(NULL);      
4708                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4709                 emitcode("cpl","a");
4710                 emitcode("add","a,#1");
4711                 emitcode("","!tlabeldef", lbl->key+100);
4712                 aopPut(AOP(result),"a",0);
4713                 emitcode("pop","acc");
4714                 lbl = newiTempLabel(NULL);      
4715                 emitcode("jnb","F0,!tlabel",lbl->key+100);
4716                 emitcode("cpl","a");
4717                 emitcode("addc","a,#0");
4718                 emitcode("","!tlabeldef", lbl->key+100);
4719                 aopPut(AOP(result),"a",1);
4720         }
4721         freeAsmop (result, NULL, ic, TRUE);
4722         /* restore EA bit in F1 */
4723         lbl = newiTempLabel(NULL);
4724         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4725         emitcode ("setb","EA");
4726         emitcode("","!tlabeldef",lbl->key+100);
4727         return ;
4728 }
4729
4730 /*-----------------------------------------------------------------*/
4731 /* genDiv - generates code for division                            */
4732 /*-----------------------------------------------------------------*/
4733 static void
4734 genDiv (iCode * ic)
4735 {
4736   operand *left = IC_LEFT (ic);
4737   operand *right = IC_RIGHT (ic);
4738   operand *result = IC_RESULT (ic);
4739
4740   D (emitcode (";", "genDiv "););
4741
4742   /* assign the amsops */
4743   AOP_OP_2 (ic);
4744
4745   /* special cases first */
4746   /* both are bits */
4747   if (AOP_TYPE (left) == AOP_CRY &&
4748       AOP_TYPE (right) == AOP_CRY)
4749     {
4750       genDivbits (left, right, result, ic);
4751       goto release;
4752     }
4753
4754   /* if both are of size == 1 */
4755   if (AOP_SIZE (left) == 1 &&
4756       AOP_SIZE (right) == 1)
4757     {
4758       genDivOneByte (left, right, result, ic);
4759       goto release;
4760     }
4761
4762   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4763           /* use the ds390 ARITHMETIC accel UNIT */
4764           genDivTwoByte (left, right, result, ic);
4765           return ;
4766   }
4767   /* should have been converted to function call */
4768   assert (0);
4769 release:
4770   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4771   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4772   freeAsmop (result, NULL, ic, TRUE);
4773 }
4774
4775 /*-----------------------------------------------------------------*/
4776 /* genModbits :- modulus of bits                                   */
4777 /*-----------------------------------------------------------------*/
4778 static void
4779 genModbits (operand * left,
4780             operand * right,
4781             operand * result,
4782             iCode   * ic)
4783 {
4784
4785   char *l;
4786
4787   /* the result must be bit */
4788   LOAD_AB_FOR_DIV (left, right, l);
4789   emitcode ("div", "ab");
4790   emitcode ("mov", "a,b");
4791   emitcode ("rrc", "a");
4792   aopOp(result, ic, TRUE, FALSE);
4793   aopPut (AOP (result), "c", 0);
4794 }
4795
4796 /*-----------------------------------------------------------------*/
4797 /* genModOneByte : 8 bit modulus                                   */
4798 /*-----------------------------------------------------------------*/
4799 static void
4800 genModOneByte (operand * left,
4801                operand * right,
4802                operand * result,
4803                iCode   * ic)
4804 {
4805   sym_link *opetype = operandType (result);
4806   char *l;
4807   symbol *lbl;
4808
4809   /* signed or unsigned */
4810   if (SPEC_USIGN (opetype))
4811     {
4812       /* unsigned is easy */
4813       LOAD_AB_FOR_DIV (left, right, l);
4814       emitcode ("div", "ab");
4815       aopOp(result, ic, TRUE, FALSE);   
4816       aopPut (AOP (result), "b", 0);
4817       return;
4818     }
4819
4820   /* signed is a little bit more difficult */
4821
4822   /* save the signs of the operands */
4823   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4824   MOVA (l);
4825
4826   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4827   emitcode ("push", "acc");     /* save it on the stack */
4828
4829   /* now sign adjust for both left & right */
4830   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4831   MOVA (l);
4832
4833   lbl = newiTempLabel (NULL);
4834   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4835   emitcode ("cpl", "a");
4836   emitcode ("inc", "a");
4837   emitcode ("", "!tlabeldef", (lbl->key + 100));
4838   emitcode ("mov", "b,a");
4839
4840   /* sign adjust left side */
4841   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4842   MOVA (l);
4843
4844   lbl = newiTempLabel (NULL);
4845   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4846   emitcode ("cpl", "a");
4847   emitcode ("inc", "a");
4848   emitcode ("", "!tlabeldef", (lbl->key + 100));
4849
4850   /* now the multiplication */
4851   emitcode ("nop", "; workaround for DS80C390 div bug.");
4852   emitcode ("div", "ab");
4853   /* we are interested in the lower order
4854      only */
4855   lbl = newiTempLabel (NULL);
4856   emitcode ("pop", "acc");
4857   /* if there was an over flow we don't
4858      adjust the sign of the result */
4859   emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4860   emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4861   CLRC;
4862   emitcode ("clr", "a");
4863   emitcode ("subb", "a,b");
4864   emitcode ("mov", "b,a");
4865   emitcode ("", "!tlabeldef", (lbl->key + 100));
4866   
4867   _G.bInUse++;
4868   /* now we are done */
4869   aopOp(result, ic, TRUE, FALSE);    
4870   aopPut (AOP (result), "b", 0);
4871   _G.bInUse--;
4872
4873 }
4874
4875 /*-----------------------------------------------------------------*/
4876 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4877 /*-----------------------------------------------------------------*/
4878 static void genModTwoByte (operand *left, operand *right, 
4879                             operand *result, iCode *ic)
4880 {
4881         sym_link *retype = getSpec(operandType(right));
4882         sym_link *letype = getSpec(operandType(left));
4883         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4884         symbol *lbl;
4885
4886         /* load up MA with left */
4887         /* save EA bit in F1 */
4888         lbl = newiTempLabel(NULL);
4889         emitcode ("setb","F1");
4890         emitcode ("jbc","EA,!tlabel",lbl->key+100);
4891         emitcode ("clr","F1");
4892         emitcode("","!tlabeldef",lbl->key+100);
4893
4894         if (!umult) {
4895                 lbl = newiTempLabel(NULL);
4896                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4897                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4898                 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4899                 emitcode ("xch", "a,b");
4900                 emitcode ("cpl","a");
4901                 emitcode ("add", "a,#1");
4902                 emitcode ("xch", "a,b");
4903                 emitcode ("cpl", "a"); // msb
4904                 emitcode ("addc","a,#0");
4905                 emitcode ("","!tlabeldef",lbl->key+100);
4906                 emitcode ("mov","ma,b");
4907                 emitcode ("mov","ma,a");
4908         } else {
4909                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4910                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4911         }
4912
4913         /* load up MB with right */
4914         if (!umult) {
4915                 if (AOP_TYPE(right) == AOP_LIT) {
4916                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4917                         if (val < 0) {
4918                                 val = -val;
4919                         } 
4920                         emitcode ("mov","mb,#!constbyte",val & 0xff);
4921                         emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);                
4922                 } else {
4923                         lbl = newiTempLabel(NULL);
4924                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4925                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4926                         emitcode ("jnb","acc.7,!tlabel",lbl->key+100);          
4927                         emitcode ("xch", "a,b");
4928                         emitcode ("cpl","a");
4929                         emitcode ("add", "a,#1");
4930                         emitcode ("xch", "a,b");
4931                         emitcode ("cpl", "a"); // msb
4932                         emitcode ("addc", "a,#0");
4933                         emitcode ("","!tlabeldef",lbl->key+100);
4934                         emitcode ("mov","mb,b");
4935                         emitcode ("mov","mb,a");
4936                 }
4937         } else {
4938                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4939                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4940         }
4941
4942         /* wait for multiplication to finish */
4943         lbl = newiTempLabel(NULL);
4944         emitcode("","!tlabeldef", lbl->key+100);
4945         emitcode("mov","a,mcnt1");
4946         emitcode("anl","a,#!constbyte",0x80);
4947         emitcode("jnz","!tlabel",lbl->key+100);
4948         
4949         freeAsmop (left, NULL, ic, TRUE);
4950         freeAsmop (right, NULL, ic,TRUE);
4951         aopOp(result, ic, TRUE, FALSE);
4952
4953         aopPut(AOP(result),"mb",1);
4954         aopPut(AOP(result),"mb",0);
4955         freeAsmop (result, NULL, ic, TRUE);
4956
4957         /* restore EA bit in F1 */
4958         lbl = newiTempLabel(NULL);
4959         emitcode ("jnb","F1,!tlabel",lbl->key+100);
4960         emitcode ("setb","EA");
4961         emitcode("","!tlabeldef",lbl->key+100);
4962         return ;
4963 }
4964
4965 /*-----------------------------------------------------------------*/
4966 /* genMod - generates code for division                            */
4967 /*-----------------------------------------------------------------*/
4968 static void
4969 genMod (iCode * ic)
4970 {
4971   operand *left = IC_LEFT (ic);
4972   operand *right = IC_RIGHT (ic);
4973   operand *result = IC_RESULT (ic);
4974
4975   D (emitcode (";", "genMod "); );
4976
4977   /* assign the amsops */
4978   AOP_OP_2 (ic);
4979
4980   /* special cases first */
4981   /* both are bits */
4982   if (AOP_TYPE (left) == AOP_CRY &&
4983       AOP_TYPE (right) == AOP_CRY)
4984     {
4985       genModbits (left, right, result, ic);
4986       goto release;
4987     }
4988
4989   /* if both are of size == 1 */
4990   if (AOP_SIZE (left) == 1 &&
4991       AOP_SIZE (right) == 1)
4992     {
4993       genModOneByte (left, right, result, ic);
4994       goto release;
4995     }
4996
4997   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4998           /* use the ds390 ARITHMETIC accel UNIT */
4999           genModTwoByte (left, right, result, ic);
5000           return ;
5001   }
5002
5003   /* should have been converted to function call */
5004   assert (0);
5005
5006 release:
5007   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5008   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5009   freeAsmop (result, NULL, ic, TRUE);
5010 }
5011
5012 /*-----------------------------------------------------------------*/
5013 /* genIfxJump :- will create a jump depending on the ifx           */
5014 /*-----------------------------------------------------------------*/
5015 static void
5016 genIfxJump (iCode * ic, char *jval)
5017 {
5018   symbol *jlbl;
5019   symbol *tlbl = newiTempLabel (NULL);
5020   char *inst;
5021
5022   D (emitcode (";", "genIfxJump ");
5023     );
5024
5025   /* if true label then we jump if condition
5026      supplied is true */
5027   if (IC_TRUE (ic))
5028     {
5029       jlbl = IC_TRUE (ic);
5030       inst = ((strcmp (jval, "a") == 0 ? "jz" :
5031                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5032     }
5033   else
5034     {
5035       /* false label is present */
5036       jlbl = IC_FALSE (ic);
5037       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5038                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5039     }
5040   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5041     emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5042   else
5043     emitcode (inst, "!tlabel", tlbl->key + 100);
5044   emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5045   emitcode ("", "!tlabeldef", tlbl->key + 100);
5046
5047   /* mark the icode as generated */
5048   ic->generated = 1;
5049 }
5050
5051 /*-----------------------------------------------------------------*/
5052 /* genCmp :- greater or less than comparison                       */
5053 /*-----------------------------------------------------------------*/
5054 static void
5055 genCmp (operand * left, operand * right,
5056         iCode * ic, iCode * ifx, int sign)
5057 {
5058   int size, offset = 0;
5059   unsigned long lit = 0L;
5060   operand *result;
5061
5062   D (emitcode (";", "genCmp");
5063     );
5064
5065   result = IC_RESULT (ic);
5066
5067   /* if left & right are bit variables */
5068   if (AOP_TYPE (left) == AOP_CRY &&
5069       AOP_TYPE (right) == AOP_CRY)
5070     {
5071       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5072       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
5073     }
5074   else
5075     {
5076       /* subtract right from left if at the
5077          end the carry flag is set then we know that
5078          left is greater than right */
5079       size = max (AOP_SIZE (left), AOP_SIZE (right));
5080
5081       /* if unsigned char cmp with lit, do cjne left,#right,zz */
5082       if ((size == 1) && !sign &&
5083           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5084         {
5085           symbol *lbl = newiTempLabel (NULL);
5086           emitcode ("cjne", "%s,%s,!tlabel",
5087                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5088                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5089                     lbl->key + 100);
5090           emitcode ("", "!tlabeldef", lbl->key + 100);
5091         }
5092       else
5093         {
5094           if (AOP_TYPE (right) == AOP_LIT)
5095             {
5096               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5097               /* optimize if(x < 0) or if(x >= 0) */
5098               if (lit == 0L)
5099                 {
5100                   if (!sign)
5101                     {
5102                       CLRC;
5103                     }
5104                   else
5105                     {
5106                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
5107
5108                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5109                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5110
5111                       aopOp (result, ic, FALSE, FALSE);
5112
5113                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5114                         {
5115                           freeAsmop (result, NULL, ic, TRUE);
5116                           genIfxJump (ifx, "acc.7");
5117                           return;
5118                         }
5119                       else
5120                         {
5121                           emitcode ("rlc", "a");
5122                         }
5123                       goto release_freedLR;
5124                     }
5125                   goto release;
5126                 }
5127             }
5128           CLRC;
5129           while (size--)
5130             {
5131               //emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5132               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5133               //emitcode (";", "genCmp #2");
5134               if (sign && (size == 0))
5135                 {
5136                     //emitcode (";", "genCmp #3");
5137                   emitcode ("xrl", "a,#!constbyte",0x80);
5138                   if (AOP_TYPE (right) == AOP_LIT)
5139                     {
5140                       unsigned long lit = (unsigned long)
5141                       floatFromVal (AOP (right)->aopu.aop_lit);
5142                       //emitcode (";", "genCmp #3.1");
5143                       emitcode ("subb", "a,#!constbyte",
5144                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5145                     }
5146                   else
5147                     {
5148                       //emitcode (";", "genCmp #3.2");
5149                       if (AOP_NEEDSACC (right))
5150                         {
5151                           emitcode ("push", "acc");
5152                         }
5153                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
5154                                                        FALSE, FALSE, FALSE));
5155                       emitcode ("xrl", "b,#!constbyte",0x80);
5156                       if (AOP_NEEDSACC (right))
5157                         {
5158                           emitcode ("pop", "acc");
5159                         }
5160                       emitcode ("subb", "a,b");
5161                     }
5162                 }
5163               else
5164                 {
5165                   const char *s;
5166
5167                   //emitcode (";", "genCmp #4");
5168                   if (AOP_NEEDSACC (right))
5169                     {
5170                       /* Yuck!! */
5171                       //emitcode (";", "genCmp #4.1");
5172                       emitcode ("xch", "a, b");
5173                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
5174                       emitcode ("xch", "a, b");
5175                       s = "b";
5176                     }
5177                   else
5178                     {
5179                       //emitcode (";", "genCmp #4.2");
5180                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
5181                     }
5182
5183                   emitcode ("subb", "a,%s", s);
5184                 }
5185             }
5186         }
5187     }
5188
5189 release:
5190 /* Don't need the left & right operands any more; do need the result. */
5191   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5192   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5193
5194   aopOp (result, ic, FALSE, FALSE);
5195
5196 release_freedLR:
5197
5198   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5199     {
5200       outBitC (result);
5201     }
5202   else
5203     {
5204       /* if the result is used in the next
5205          ifx conditional branch then generate
5206          code a little differently */
5207       if (ifx)
5208         {
5209           genIfxJump (ifx, "c");
5210         }
5211       else
5212         {
5213           outBitC (result);
5214         }
5215       /* leave the result in acc */
5216     }
5217   freeAsmop (result, NULL, ic, TRUE);
5218 }
5219
5220 /*-----------------------------------------------------------------*/
5221 /* genCmpGt :- greater than comparison                             */
5222 /*-----------------------------------------------------------------*/
5223 static void
5224 genCmpGt (iCode * ic, iCode * ifx)
5225 {
5226   operand *left, *right;
5227   sym_link *letype, *retype;
5228   int sign;
5229
5230   D (emitcode (";", "genCmpGt ");
5231     );
5232
5233   left = IC_LEFT (ic);
5234   right = IC_RIGHT (ic);
5235
5236   letype = getSpec (operandType (left));
5237   retype = getSpec (operandType (right));
5238   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5239
5240   /* assign the left & right amsops */
5241   AOP_OP_2 (ic);
5242
5243   genCmp (right, left, ic, ifx, sign);
5244 }
5245
5246 /*-----------------------------------------------------------------*/
5247 /* genCmpLt - less than comparisons                                */
5248 /*-----------------------------------------------------------------*/
5249 static void
5250 genCmpLt (iCode * ic, iCode * ifx)
5251 {
5252   operand *left, *right;
5253   sym_link *letype, *retype;
5254   int sign;
5255
5256   D (emitcode (";", "genCmpLt "););
5257
5258   left = IC_LEFT (ic);
5259   right = IC_RIGHT (ic);
5260
5261   letype = getSpec (operandType (left));
5262   retype = getSpec (operandType (right));
5263   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5264
5265   /* assign the left & right amsops */
5266   AOP_OP_2 (ic);
5267
5268   genCmp (left, right, ic, ifx, sign);
5269 }
5270
5271 /*-----------------------------------------------------------------*/
5272 /* gencjneshort - compare and jump if not equal                    */
5273 /*-----------------------------------------------------------------*/
5274 static void
5275 gencjneshort (operand * left, operand * right, symbol * lbl)
5276 {
5277   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5278   int offset = 0;
5279   unsigned long lit = 0L;
5280
5281   D (emitcode (";", "gencjneshort");
5282     );
5283
5284   /* if the left side is a literal or
5285      if the right is in a pointer register and left
5286      is not */
5287   if ((AOP_TYPE (left) == AOP_LIT) ||
5288       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5289     {
5290       operand *t = right;
5291       right = left;
5292       left = t;
5293     }
5294
5295   if (AOP_TYPE (right) == AOP_LIT)
5296     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5297
5298   if (opIsGptr (left) || opIsGptr (right))
5299     {
5300       /* We are comparing a generic pointer to something.
5301        * Exclude the generic type byte from the comparison.
5302        */
5303       size--;
5304       D (emitcode (";", "cjneshort: generic ptr special case.");
5305         )
5306     }
5307
5308
5309   /* if the right side is a literal then anything goes */
5310   if (AOP_TYPE (right) == AOP_LIT &&
5311       AOP_TYPE (left) != AOP_DIR)
5312     {
5313       while (size--)
5314         {
5315           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5316           MOVA (l);
5317           emitcode ("cjne", "a,%s,!tlabel",
5318                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5319                     lbl->key + 100);
5320           offset++;
5321         }
5322     }
5323
5324   /* if the right side is in a register or in direct space or
5325      if the left is a pointer register & right is not */
5326   else if (AOP_TYPE (right) == AOP_REG ||
5327            AOP_TYPE (right) == AOP_DIR ||
5328            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5329            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5330     {
5331       while (size--)
5332         {
5333           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5334           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5335               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5336             emitcode ("jnz", "!tlabel", lbl->key + 100);
5337           else
5338             emitcode ("cjne", "a,%s,!tlabel",
5339                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5340                       lbl->key + 100);
5341           offset++;
5342         }
5343     }
5344   else
5345     {
5346       /* right is a pointer reg need both a & b */
5347       while (size--)
5348         {
5349           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5350           if (strcmp (l, "b"))
5351             emitcode ("mov", "b,%s", l);
5352           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5353           emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5354           offset++;
5355         }
5356     }
5357 }
5358
5359 /*-----------------------------------------------------------------*/
5360 /* gencjne - compare and jump if not equal                         */
5361 /*-----------------------------------------------------------------*/
5362 static void
5363 gencjne (operand * left, operand * right, symbol * lbl)
5364 {
5365   symbol *tlbl = newiTempLabel (NULL);
5366
5367   D (emitcode (";", "gencjne");
5368     );
5369
5370   gencjneshort (left, right, lbl);
5371
5372   emitcode ("mov", "a,%s", one);
5373   emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5374   emitcode ("", "!tlabeldef", lbl->key + 100);
5375   emitcode ("clr", "a");
5376   emitcode ("", "!tlabeldef", tlbl->key + 100);
5377 }
5378
5379 /*-----------------------------------------------------------------*/
5380 /* genCmpEq - generates code for equal to                          */
5381 /*-----------------------------------------------------------------*/
5382 static void
5383 genCmpEq (iCode * ic, iCode * ifx)
5384 {
5385   operand *left, *right, *result;
5386
5387   D (emitcode (";", "genCmpEq ");
5388     );
5389
5390   AOP_OP_2 (ic);
5391   AOP_SET_LOCALS (ic);
5392
5393   /* if literal, literal on the right or
5394      if the right is in a pointer register and left
5395      is not */
5396   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5397       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5398     {
5399       operand *t = IC_RIGHT (ic);
5400       IC_RIGHT (ic) = IC_LEFT (ic);
5401       IC_LEFT (ic) = t;
5402     }
5403
5404   if (ifx &&                    /* !AOP_SIZE(result) */
5405       OP_SYMBOL (result) &&
5406       OP_SYMBOL (result)->regType == REG_CND)
5407     {
5408       symbol *tlbl;
5409       /* if they are both bit variables */
5410       if (AOP_TYPE (left) == AOP_CRY &&
5411           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5412         {
5413           if (AOP_TYPE (right) == AOP_LIT)
5414             {
5415               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5416               if (lit == 0L)
5417                 {
5418                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5419                   emitcode ("cpl", "c");
5420                 }
5421               else if (lit == 1L)
5422                 {
5423                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5424                 }
5425               else
5426                 {
5427                   emitcode ("clr", "c");
5428                 }
5429               /* AOP_TYPE(right) == AOP_CRY */
5430             }
5431           else
5432             {
5433               symbol *lbl = newiTempLabel (NULL);
5434               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5435               emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5436               emitcode ("cpl", "c");
5437               emitcode ("", "!tlabeldef", (lbl->key + 100));
5438             }
5439           /* if true label then we jump if condition
5440              supplied is true */
5441           tlbl = newiTempLabel (NULL);
5442           if (IC_TRUE (ifx))
5443             {
5444               emitcode ("jnc", "!tlabel", tlbl->key + 100);
5445               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5446             }
5447           else
5448             {
5449               emitcode ("jc", "!tlabel", tlbl->key + 100);
5450               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5451             }
5452           emitcode ("", "!tlabeldef", tlbl->key + 100);
5453         }
5454       else
5455         {
5456           tlbl = newiTempLabel (NULL);
5457           gencjneshort (left, right, tlbl);
5458           if (IC_TRUE (ifx))
5459             {
5460               emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5461               emitcode ("", "!tlabeldef", tlbl->key + 100);
5462             }
5463           else
5464             {
5465               symbol *lbl = newiTempLabel (NULL);
5466               emitcode ("sjmp", "!tlabel", lbl->key + 100);
5467               emitcode ("", "!tlabeldef", tlbl->key + 100);
5468               emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5469               emitcode ("", "!tlabeldef", lbl->key + 100);
5470             }
5471         }
5472       /* mark the icode as generated */
5473       ifx->generated = 1;
5474
5475       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5476       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5477       return;
5478     }
5479
5480   /* if they are both bit variables */
5481   if (AOP_TYPE (left) == AOP_CRY &&
5482       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5483     {
5484       if (AOP_TYPE (right) == AOP_LIT)
5485         {
5486           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5487           if (lit == 0L)
5488             {
5489               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5490               emitcode ("cpl", "c");
5491             }
5492           else if (lit == 1L)
5493             {
5494               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5495             }
5496           else
5497             {
5498               emitcode ("clr", "c");
5499             }
5500           /* AOP_TYPE(right) == AOP_CRY */
5501         }
5502       else
5503         {
5504           symbol *lbl = newiTempLabel (NULL);
5505           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5506           emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5507           emitcode ("cpl", "c");
5508           emitcode ("", "!tlabeldef", (lbl->key + 100));
5509         }
5510
5511       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5512       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5513
5514       aopOp (result, ic, TRUE, FALSE);
5515
5516       /* c = 1 if egal */
5517       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5518         {
5519           outBitC (result);
5520           goto release;
5521         }
5522       if (ifx)
5523         {
5524           genIfxJump (ifx, "c");
5525           goto release;
5526         }
5527       /* if the result is used in an arithmetic operation
5528          then put the result in place */
5529       outBitC (result);
5530     }
5531   else
5532     {
5533       gencjne (left, right, newiTempLabel (NULL));
5534
5535       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5536       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5537
5538       aopOp (result, ic, TRUE, FALSE);
5539
5540       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5541         {
5542           aopPut (AOP (result), "a", 0);
5543           goto release;
5544         }
5545       if (ifx)
5546         {
5547           genIfxJump (ifx, "a");
5548           goto release;
5549         }
5550       /* if the result is used in an arithmetic operation
5551          then put the result in place */
5552       if (AOP_TYPE (result) != AOP_CRY)
5553         outAcc (result);
5554       /* leave the result in acc */
5555     }
5556
5557 release:
5558   freeAsmop (result, NULL, ic, TRUE);
5559 }
5560
5561 /*-----------------------------------------------------------------*/
5562 /* ifxForOp - returns the icode containing the ifx for operand     */
5563 /*-----------------------------------------------------------------*/
5564 static iCode *
5565 ifxForOp (operand * op, iCode * ic)
5566 {
5567   /* if true symbol then needs to be assigned */
5568   if (IS_TRUE_SYMOP (op))
5569     return NULL;
5570
5571   /* if this has register type condition and
5572      the next instruction is ifx with the same operand
5573      and live to of the operand is upto the ifx only then */
5574   if (ic->next &&
5575       ic->next->op == IFX &&
5576       IC_COND (ic->next)->key == op->key &&
5577       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5578     return ic->next;
5579
5580   return NULL;
5581 }
5582 /*-----------------------------------------------------------------*/
5583 /* hasInc - operand is incremented before any other use            */
5584 /*-----------------------------------------------------------------*/
5585 static iCode *
5586 hasInc (operand *op, iCode *ic, int osize)
5587 {
5588   sym_link *type = operandType(op);
5589   sym_link *retype = getSpec (type);
5590   iCode *lic = ic->next;
5591   int isize ;
5592   
5593   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5594   if (!IS_SYMOP(op)) return NULL;
5595
5596   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5597   if (IS_AGGREGATE(type->next)) return NULL;
5598   if (osize != (isize = getSize(type->next))) return NULL;
5599
5600   while (lic) {
5601       /* if operand of the form op = op + <sizeof *op> */
5602       if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5603           isOperandEqual(IC_RESULT(lic),op) && 
5604           isOperandLiteral(IC_RIGHT(lic)) &&
5605           operandLitValue(IC_RIGHT(lic)) == isize) {
5606           return lic;
5607       }
5608       /* if the operand used or deffed */
5609       if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5610           return NULL;
5611       }
5612       /* if GOTO or IFX */
5613       if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5614       lic = lic->next;
5615   }
5616   return NULL;
5617 }
5618
5619 /*-----------------------------------------------------------------*/
5620 /* genAndOp - for && operation                                     */
5621 /*-----------------------------------------------------------------*/
5622 static void
5623 genAndOp (iCode * ic)
5624 {
5625   operand *left, *right, *result;
5626   symbol *tlbl;
5627
5628   D (emitcode (";", "genAndOp "););
5629
5630   /* note here that && operations that are in an
5631      if statement are taken away by backPatchLabels
5632      only those used in arthmetic operations remain */
5633   AOP_OP_2 (ic);
5634   AOP_SET_LOCALS (ic);
5635
5636   /* if both are bit variables */
5637   if (AOP_TYPE (left) == AOP_CRY &&
5638       AOP_TYPE (right) == AOP_CRY)
5639     {
5640       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5641       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5642       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5643       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5644   
5645       aopOp (result,ic,FALSE, FALSE);
5646       outBitC (result);
5647     }
5648   else
5649     {
5650       tlbl = newiTempLabel (NULL);
5651       toBoolean (left);
5652       emitcode ("jz", "!tlabel", tlbl->key + 100);
5653       toBoolean (right);
5654       emitcode ("", "!tlabeldef", tlbl->key + 100);
5655       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5656       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5657   
5658       aopOp (result,ic,FALSE, FALSE);
5659       outBitAcc (result);
5660     }
5661     freeAsmop (result, NULL, ic, TRUE);
5662 }
5663
5664
5665 /*-----------------------------------------------------------------*/
5666 /* genOrOp - for || operation                                      */
5667 /*-----------------------------------------------------------------*/
5668 static void
5669 genOrOp (iCode * ic)
5670 {
5671   operand *left, *right, *result;
5672   symbol *tlbl;
5673
5674   D (emitcode (";", "genOrOp "););
5675
5676   /* note here that || operations that are in an
5677      if statement are taken away by backPatchLabels
5678      only those used in arthmetic operations remain */
5679   AOP_OP_2 (ic);
5680   AOP_SET_LOCALS (ic);
5681
5682   /* if both are bit variables */
5683   if (AOP_TYPE (left) == AOP_CRY &&
5684       AOP_TYPE (right) == AOP_CRY)
5685     {
5686       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5687       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5688       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5689       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5690   
5691       aopOp (result,ic,FALSE, FALSE);
5692       
5693       outBitC (result);
5694     }
5695   else
5696     {
5697       tlbl = newiTempLabel (NULL);
5698       toBoolean (left);
5699       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5700       toBoolean (right);
5701       emitcode ("", "!tlabeldef", tlbl->key + 100);
5702       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5703       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5704   
5705       aopOp (result,ic,FALSE, FALSE);
5706       
5707       outBitAcc (result);
5708     }
5709
5710   freeAsmop (result, NULL, ic, TRUE);
5711 }
5712
5713 /*-----------------------------------------------------------------*/
5714 /* isLiteralBit - test if lit == 2^n                               */
5715 /*-----------------------------------------------------------------*/
5716 static int
5717 isLiteralBit (unsigned long lit)
5718 {
5719   unsigned long pw[32] =
5720   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5721    0x100L, 0x200L, 0x400L, 0x800L,
5722    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5723    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5724    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5725    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5726    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5727   int idx;
5728
5729   for (idx = 0; idx < 32; idx++)
5730     if (lit == pw[idx])
5731       return idx + 1;
5732   return 0;
5733 }
5734
5735 /*-----------------------------------------------------------------*/
5736 /* continueIfTrue -                                                */
5737 /*-----------------------------------------------------------------*/
5738 static void
5739 continueIfTrue (iCode * ic)
5740 {
5741   if (IC_TRUE (ic))
5742     emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5743   ic->generated = 1;
5744 }
5745
5746 /*-----------------------------------------------------------------*/
5747 /* jmpIfTrue -                                                     */
5748 /*-----------------------------------------------------------------*/
5749 static void
5750 jumpIfTrue (iCode * ic)
5751 {
5752   if (!IC_TRUE (ic))
5753     emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5754   ic->generated = 1;
5755 }
5756
5757 /*-----------------------------------------------------------------*/
5758 /* jmpTrueOrFalse -                                                */
5759 /*-----------------------------------------------------------------*/
5760 static void
5761 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5762 {
5763   // ugly but optimized by peephole
5764   if (IC_TRUE (ic))
5765     {
5766       symbol *nlbl = newiTempLabel (NULL);
5767       emitcode ("sjmp", "!tlabel", nlbl->key + 100);
5768       emitcode ("", "!tlabeldef", tlbl->key + 100);
5769       emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
5770       emitcode ("", "!tlabeldef", nlbl->key + 100);
5771     }
5772   else
5773     {
5774       emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
5775       emitcode ("", "!tlabeldef", tlbl->key + 100);
5776     }
5777   ic->generated = 1;
5778 }
5779
5780 // Generate code to perform a bit-wise logic operation
5781 // on two operands in far space (assumed to already have been 
5782 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5783 // in far space. This requires pushing the result on the stack
5784 // then popping it into the result.
5785 static void
5786 genFarFarLogicOp(iCode *ic, char *logicOp)
5787 {
5788       int size, resultSize, compSize;
5789       int offset = 0;
5790       
5791       TR_AP("#5");
5792       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5793       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5794                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5795       
5796       _startLazyDPSEvaluation();
5797       for (size = compSize; (size--); offset++)
5798       {
5799           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5800           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5801           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5802           
5803           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5804           emitcode ("push", "acc");
5805       }
5806       _endLazyDPSEvaluation();
5807      
5808       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5809       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5810       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5811      
5812       resultSize = AOP_SIZE(IC_RESULT(ic));
5813
5814       ADJUST_PUSHED_RESULT(compSize, resultSize);
5815
5816       _startLazyDPSEvaluation();
5817       while (compSize--)
5818       {
5819           emitcode ("pop", "acc");
5820           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5821       }
5822       _endLazyDPSEvaluation();
5823       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5824 }
5825
5826
5827 /*-----------------------------------------------------------------*/
5828 /* genAnd  - code for and                                          */
5829 /*-----------------------------------------------------------------*/
5830 static void
5831 genAnd (iCode * ic, iCode * ifx)
5832 {
5833   operand *left, *right, *result;
5834   int size, offset = 0;
5835   unsigned long lit = 0L;
5836   int bytelit = 0;
5837   char buffer[10];
5838   bool pushResult;
5839
5840   D (emitcode (";", "genAnd "););
5841
5842   AOP_OP_3_NOFATAL (ic, pushResult);
5843   AOP_SET_LOCALS (ic);
5844
5845   if (pushResult)
5846   {
5847       genFarFarLogicOp(ic, "anl");
5848       return;
5849   }  
5850
5851 #ifdef DEBUG_TYPE
5852   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5853             AOP_TYPE (result),
5854             AOP_TYPE (left), AOP_TYPE (right));
5855   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5856             AOP_SIZE (result),
5857             AOP_SIZE (left), AOP_SIZE (right));
5858 #endif
5859
5860   /* if left is a literal & right is not then exchange them */
5861   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5862 #ifdef LOGIC_OPS_BROKEN      
5863     ||  AOP_NEEDSACC (left)
5864 #endif
5865     )
5866     {
5867       operand *tmp = right;
5868       right = left;
5869       left = tmp;
5870     }
5871
5872   /* if result = right then exchange them */
5873   if (sameRegs (AOP (result), AOP (right)))
5874     {
5875       operand *tmp = right;
5876       right = left;
5877       left = tmp;
5878     }
5879
5880   /* if right is bit then exchange them */
5881   if (AOP_TYPE (right) == AOP_CRY &&
5882       AOP_TYPE (left) != AOP_CRY)
5883     {
5884       operand *tmp = right;
5885       right = left;
5886       left = tmp;
5887     }
5888   if (AOP_TYPE (right) == AOP_LIT)
5889     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5890
5891   size = AOP_SIZE (result);
5892
5893   // if(bit & yy)
5894   // result = bit & yy;
5895   if (AOP_TYPE (left) == AOP_CRY)
5896     {
5897       // c = bit & literal;
5898       if (AOP_TYPE (right) == AOP_LIT)
5899         {
5900           if (lit & 1)
5901             {
5902               if (size && sameRegs (AOP (result), AOP (left)))
5903                 // no change
5904                 goto release;
5905               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5906             }
5907           else
5908             {
5909               // bit(result) = 0;
5910               if (size && (AOP_TYPE (result) == AOP_CRY))
5911                 {
5912                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5913                   goto release;
5914                 }
5915               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5916                 {
5917                   jumpIfTrue (ifx);
5918                   goto release;
5919                 }
5920               emitcode ("clr", "c");
5921             }
5922         }
5923       else
5924         {
5925           if (AOP_TYPE (right) == AOP_CRY)
5926             {
5927               // c = bit & bit;
5928               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5929               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5930             }
5931           else
5932             {
5933               // c = bit & val;
5934               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5935               // c = lsb
5936               emitcode ("rrc", "a");
5937               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5938             }
5939         }
5940       // bit = c
5941       // val = c
5942       if (size)
5943         outBitC (result);
5944       // if(bit & ...)
5945       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5946         genIfxJump (ifx, "c");
5947       goto release;
5948     }
5949
5950   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5951   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5952   if ((AOP_TYPE (right) == AOP_LIT) &&
5953       (AOP_TYPE (result) == AOP_CRY) &&
5954       (AOP_TYPE (left) != AOP_CRY))
5955     {
5956       int posbit = isLiteralBit (lit);
5957       /* left &  2^n */
5958       if (posbit)
5959         {
5960           posbit--;
5961           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5962           // bit = left & 2^n
5963           if (size)
5964             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5965           // if(left &  2^n)
5966           else
5967             {
5968               if (ifx)
5969                 {
5970                   sprintf (buffer, "acc.%d", posbit & 0x07);
5971                   genIfxJump (ifx, buffer);
5972                 }
5973               goto release;
5974             }
5975         }
5976       else
5977         {
5978           symbol *tlbl = newiTempLabel (NULL);
5979           int sizel = AOP_SIZE (left);
5980           if (size)
5981             emitcode ("setb", "c");
5982           while (sizel--)
5983             {
5984               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5985                 {
5986                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5987                   // byte ==  2^n ?
5988                   if ((posbit = isLiteralBit (bytelit)) != 0)
5989                     emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
5990                   else
5991                     {
5992                       if (bytelit != 0x0FFL)
5993                         emitcode ("anl", "a,%s",
5994                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5995                       emitcode ("jnz", "!tlabel", tlbl->key + 100);
5996                     }
5997                 }
5998               offset++;
5999             }
6000           // bit = left & literal
6001           if (size)
6002             {
6003               emitcode ("clr", "c");
6004               emitcode ("", "!tlabeldef", tlbl->key + 100);
6005             }
6006           // if(left & literal)
6007           else
6008             {
6009               if (ifx)
6010                 jmpTrueOrFalse (ifx, tlbl);
6011               goto release;
6012             }
6013         }
6014       outBitC (result);
6015       goto release;
6016     }
6017
6018   /* if left is same as result */
6019   if (sameRegs (AOP (result), AOP (left)))
6020     {
6021       for (; size--; offset++)
6022         {
6023           if (AOP_TYPE (right) == AOP_LIT)
6024             {
6025               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6026                 continue;
6027               else if (bytelit == 0)
6028                 aopPut (AOP (result), zero, offset);
6029               else if (IS_AOP_PREG (result))
6030                 {
6031                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6032                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6033                   aopPut (AOP (result), "a", offset);
6034                 }
6035               else
6036                 emitcode ("anl", "%s,%s",
6037                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6038                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6039             }
6040           else
6041             {
6042               if (AOP_TYPE (left) == AOP_ACC)
6043                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6044               else
6045                 {
6046                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6047                   if (IS_AOP_PREG (result))
6048                     {
6049                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6050                       aopPut (AOP (result), "a", offset);
6051
6052                     }
6053                   else
6054                     emitcode ("anl", "%s,a",
6055                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6056                 }
6057             }
6058         }
6059     }
6060   else
6061     {
6062       // left & result in different registers
6063       if (AOP_TYPE (result) == AOP_CRY)
6064         {
6065           // result = bit
6066           // if(size), result in bit
6067           // if(!size && ifx), conditional oper: if(left & right)
6068           symbol *tlbl = newiTempLabel (NULL);
6069           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6070           if (size)
6071             emitcode ("setb", "c");
6072           while (sizer--)
6073             {
6074               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6075                 emitcode ("anl", "a,%s",
6076                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6077               } else {
6078                 if (AOP_TYPE(left)==AOP_ACC) {
6079                   emitcode("mov", "b,a");
6080                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6081                   emitcode("anl", "a,b");
6082                 }else {
6083                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6084                   emitcode ("anl", "a,%s",
6085                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6086                 }
6087               }
6088               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6089               offset++;
6090             }
6091           if (size)
6092             {
6093               CLRC;
6094               emitcode ("", "!tlabeldef", tlbl->key + 100);
6095               outBitC (result);
6096             }
6097           else if (ifx)
6098             jmpTrueOrFalse (ifx, tlbl);
6099         }
6100       else
6101         {
6102           for (; (size--); offset++)
6103             {
6104               // normal case
6105               // result = left & right
6106               if (AOP_TYPE (right) == AOP_LIT)
6107                 {
6108                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6109                     {
6110                       aopPut (AOP (result),
6111                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6112                               offset);
6113                       continue;
6114                     }
6115                   else if (bytelit == 0)
6116                     {
6117                       aopPut (AOP (result), zero, offset);
6118                       continue;
6119                     }
6120                   D (emitcode (";", "better literal AND."););
6121                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6122                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6123                                                     FALSE, FALSE, FALSE));
6124
6125                 }
6126               else
6127                 {
6128                   // faster than result <- left, anl result,right
6129                   // and better if result is SFR
6130                   if (AOP_TYPE (left) == AOP_ACC)
6131                     {
6132                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
6133                                                        FALSE, FALSE, FALSE));
6134                     }
6135                   else
6136                     {
6137                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6138                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6139                       {
6140                           emitcode("mov", "b,a");
6141                           rOp = "b";
6142                       }
6143                         
6144                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6145                       emitcode ("anl", "a,%s", rOp);
6146                     }                   
6147                 }
6148               aopPut (AOP (result), "a", offset);
6149             }
6150         }
6151     }
6152
6153 release:
6154   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6155   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6156   freeAsmop (result, NULL, ic, TRUE);
6157 }
6158
6159
6160 /*-----------------------------------------------------------------*/
6161 /* genOr  - code for or                                            */
6162 /*-----------------------------------------------------------------*/
6163 static void
6164 genOr (iCode * ic, iCode * ifx)
6165 {
6166   operand *left, *right, *result;
6167   int size, offset = 0;
6168   unsigned long lit = 0L;
6169   bool     pushResult;
6170
6171   D (emitcode (";", "genOr "););
6172
6173   AOP_OP_3_NOFATAL (ic, pushResult);
6174   AOP_SET_LOCALS (ic);
6175
6176   if (pushResult)
6177   {
6178       genFarFarLogicOp(ic, "orl");
6179       return;
6180   }
6181
6182
6183 #ifdef DEBUG_TYPE
6184   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6185             AOP_TYPE (result),
6186             AOP_TYPE (left), AOP_TYPE (right));
6187   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6188             AOP_SIZE (result),
6189             AOP_SIZE (left), AOP_SIZE (right));
6190 #endif
6191
6192   /* if left is a literal & right is not then exchange them */
6193   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6194 #ifdef LOGIC_OPS_BROKEN
6195    || AOP_NEEDSACC (left) // I think this is a net loss now.
6196 #endif      
6197       )
6198     {
6199       operand *tmp = right;
6200       right = left;
6201       left = tmp;
6202     }
6203
6204   /* if result = right then exchange them */
6205   if (sameRegs (AOP (result), AOP (right)))
6206     {
6207       operand *tmp = right;
6208       right = left;
6209       left = tmp;
6210     }
6211
6212   /* if right is bit then exchange them */
6213   if (AOP_TYPE (right) == AOP_CRY &&
6214       AOP_TYPE (left) != AOP_CRY)
6215     {
6216       operand *tmp = right;
6217       right = left;
6218       left = tmp;
6219     }
6220   if (AOP_TYPE (right) == AOP_LIT)
6221     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6222
6223   size = AOP_SIZE (result);
6224
6225   // if(bit | yy)
6226   // xx = bit | yy;
6227   if (AOP_TYPE (left) == AOP_CRY)
6228     {
6229       if (AOP_TYPE (right) == AOP_LIT)
6230         {
6231           // c = bit & literal;
6232           if (lit)
6233             {
6234               // lit != 0 => result = 1
6235               if (AOP_TYPE (result) == AOP_CRY)
6236                 {
6237                   if (size)
6238                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6239                   else if (ifx)
6240                     continueIfTrue (ifx);
6241                   goto release;
6242                 }
6243               emitcode ("setb", "c");
6244             }
6245           else
6246             {
6247               // lit == 0 => result = left
6248               if (size && sameRegs (AOP (result), AOP (left)))
6249                 goto release;
6250               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6251             }
6252         }
6253       else
6254         {
6255           if (AOP_TYPE (right) == AOP_CRY)
6256             {
6257               // c = bit | bit;
6258               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6259               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6260             }
6261           else
6262             {
6263               // c = bit | val;
6264               symbol *tlbl = newiTempLabel (NULL);
6265               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6266                 emitcode ("setb", "c");
6267               emitcode ("jb", "%s,!tlabel",
6268                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
6269               toBoolean (right);
6270               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6271               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6272                 {
6273                   jmpTrueOrFalse (ifx, tlbl);
6274                   goto release;
6275                 }
6276               else
6277                 {
6278                   CLRC;
6279                   emitcode ("", "!tlabeldef", tlbl->key + 100);
6280                 }
6281             }
6282         }
6283       // bit = c
6284       // val = c
6285       if (size)
6286         outBitC (result);
6287       // if(bit | ...)
6288       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6289         genIfxJump (ifx, "c");
6290       goto release;
6291     }
6292
6293   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6294   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6295   if ((AOP_TYPE (right) == AOP_LIT) &&
6296       (AOP_TYPE (result) == AOP_CRY) &&
6297       (AOP_TYPE (left) != AOP_CRY))
6298     {
6299       if (lit)
6300         {
6301           // result = 1
6302           if (size)
6303             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6304           else
6305             continueIfTrue (ifx);
6306           goto release;
6307         }
6308       else
6309         {
6310           // lit = 0, result = boolean(left)
6311           if (size)
6312             emitcode ("setb", "c");
6313           toBoolean (right);
6314           if (size)
6315             {
6316               symbol *tlbl = newiTempLabel (NULL);
6317               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6318               CLRC;
6319               emitcode ("", "!tlabeldef", tlbl->key + 100);
6320             }
6321           else
6322             {
6323               genIfxJump (ifx, "a");
6324               goto release;
6325             }
6326         }
6327       outBitC (result);
6328       goto release;
6329     }
6330
6331   /* if left is same as result */
6332   if (sameRegs (AOP (result), AOP (left)))
6333     {
6334       for (; size--; offset++)
6335         {
6336           if (AOP_TYPE (right) == AOP_LIT)
6337             {
6338               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6339                 {
6340                   continue;
6341                 }
6342               else
6343                 {
6344                   if (IS_AOP_PREG (left))
6345                     {
6346                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6347                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6348                       aopPut (AOP (result), "a", offset);
6349                     }
6350                   else
6351                     {
6352                       emitcode ("orl", "%s,%s",
6353                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6354                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6355                     }
6356                 }
6357             }
6358           else
6359             {
6360               if (AOP_TYPE (left) == AOP_ACC)
6361                 {
6362                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6363                 }
6364               else
6365                 {
6366                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6367                   if (IS_AOP_PREG (left))
6368                     {
6369                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6370                       aopPut (AOP (result), "a", offset);
6371                     }
6372                   else
6373                     {
6374                       emitcode ("orl", "%s,a",
6375                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6376                     }
6377                 }
6378             }
6379         }
6380     }
6381   else
6382     {
6383       // left & result in different registers
6384       if (AOP_TYPE (result) == AOP_CRY)
6385         {
6386           // result = bit
6387           // if(size), result in bit
6388           // if(!size && ifx), conditional oper: if(left | right)
6389           symbol *tlbl = newiTempLabel (NULL);
6390           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6391           if (size)
6392             emitcode ("setb", "c");
6393           while (sizer--)
6394             {
6395               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6396                 emitcode ("orl", "a,%s",
6397                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6398               } else {
6399                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6400                 emitcode ("orl", "a,%s",
6401                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6402               }
6403               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6404               offset++;
6405             }
6406           if (size)
6407             {
6408               CLRC;
6409               emitcode ("", "!tlabeldef", tlbl->key + 100);
6410               outBitC (result);
6411             }
6412           else if (ifx)
6413             jmpTrueOrFalse (ifx, tlbl);
6414         }
6415       else
6416         {
6417             _startLazyDPSEvaluation();
6418           for (; (size--); offset++)
6419             {
6420               // normal case
6421               // result = left & right
6422               if (AOP_TYPE (right) == AOP_LIT)
6423                 {
6424                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6425                     {
6426                       aopPut (AOP (result),
6427                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6428                               offset);
6429                       continue;
6430                     }
6431                   D (emitcode (";", "better literal OR."););
6432                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6433                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6434                                                     FALSE, FALSE, FALSE));
6435
6436                 }
6437               else
6438                 {
6439                   // faster than result <- left, anl result,right
6440                   // and better if result is SFR
6441                   if (AOP_TYPE (left) == AOP_ACC)
6442                     {
6443                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6444                                                        FALSE, FALSE, FALSE));
6445                     }
6446                   else
6447                     {
6448                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6449                         
6450                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6451                       {
6452                           emitcode("mov", "b,a");
6453                           rOp = "b";
6454                       }
6455                         
6456                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6457                       emitcode ("orl", "a,%s", rOp);
6458                     }
6459                 }
6460               aopPut (AOP (result), "a", offset);
6461             }
6462             _endLazyDPSEvaluation();
6463         }
6464     }
6465
6466 release:
6467   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6468   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6469   freeAsmop (result, NULL, ic, TRUE);
6470 }
6471
6472 /*-----------------------------------------------------------------*/
6473 /* genXor - code for xclusive or                                   */
6474 /*-----------------------------------------------------------------*/
6475 static void
6476 genXor (iCode * ic, iCode * ifx)
6477 {
6478   operand *left, *right, *result;
6479   int size, offset = 0;
6480   unsigned long lit = 0L;
6481   bool pushResult;
6482
6483   D (emitcode (";", "genXor "););
6484
6485   AOP_OP_3_NOFATAL (ic, pushResult);
6486   AOP_SET_LOCALS (ic);
6487
6488   if (pushResult)
6489   {
6490       genFarFarLogicOp(ic, "xrl");
6491       return;
6492   }  
6493
6494 #ifdef DEBUG_TYPE
6495   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6496             AOP_TYPE (result),
6497             AOP_TYPE (left), AOP_TYPE (right));
6498   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6499             AOP_SIZE (result),
6500             AOP_SIZE (left), AOP_SIZE (right));
6501 #endif
6502
6503   /* if left is a literal & right is not ||
6504      if left needs acc & right does not */
6505   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6506 #ifdef LOGIC_OPS_BROKEN      
6507       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6508 #endif
6509      )
6510     {
6511       operand *tmp = right;
6512       right = left;
6513       left = tmp;
6514     }
6515
6516   /* if result = right then exchange them */
6517   if (sameRegs (AOP (result), AOP (right)))
6518     {
6519       operand *tmp = right;
6520       right = left;
6521       left = tmp;
6522     }
6523
6524   /* if right is bit then exchange them */
6525   if (AOP_TYPE (right) == AOP_CRY &&
6526       AOP_TYPE (left) != AOP_CRY)
6527     {
6528       operand *tmp = right;
6529       right = left;
6530       left = tmp;
6531     }
6532   if (AOP_TYPE (right) == AOP_LIT)
6533     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6534
6535   size = AOP_SIZE (result);
6536
6537   // if(bit ^ yy)
6538   // xx = bit ^ yy;
6539   if (AOP_TYPE (left) == AOP_CRY)
6540     {
6541       if (AOP_TYPE (right) == AOP_LIT)
6542         {
6543           // c = bit & literal;
6544           if (lit >> 1)
6545             {
6546               // lit>>1  != 0 => result = 1
6547               if (AOP_TYPE (result) == AOP_CRY)
6548                 {
6549                   if (size)
6550                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6551                   else if (ifx)
6552                     continueIfTrue (ifx);
6553                   goto release;
6554                 }
6555               emitcode ("setb", "c");
6556             }
6557           else
6558             {
6559               // lit == (0 or 1)
6560               if (lit == 0)
6561                 {
6562                   // lit == 0, result = left
6563                   if (size && sameRegs (AOP (result), AOP (left)))
6564                     goto release;
6565                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6566                 }
6567               else
6568                 {
6569                   // lit == 1, result = not(left)
6570                   if (size && sameRegs (AOP (result), AOP (left)))
6571                     {
6572                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6573                       goto release;
6574                     }
6575                   else
6576                     {
6577                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6578                       emitcode ("cpl", "c");
6579                     }
6580                 }
6581             }
6582
6583         }
6584       else
6585         {
6586           // right != literal
6587           symbol *tlbl = newiTempLabel (NULL);
6588           if (AOP_TYPE (right) == AOP_CRY)
6589             {
6590               // c = bit ^ bit;
6591               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6592             }
6593           else
6594             {
6595               int sizer = AOP_SIZE (right);
6596               // c = bit ^ val
6597               // if val>>1 != 0, result = 1
6598               emitcode ("setb", "c");
6599               while (sizer)
6600                 {
6601                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6602                   if (sizer == 1)
6603                     // test the msb of the lsb
6604                     emitcode ("anl", "a,#!constbyte",0xfe);
6605                   emitcode ("jnz", "!tlabel", tlbl->key + 100);
6606                   sizer--;
6607                 }
6608               // val = (0,1)
6609               emitcode ("rrc", "a");
6610             }
6611           emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6612           emitcode ("cpl", "c");
6613           emitcode ("", "!tlabeldef", (tlbl->key + 100));
6614         }
6615       // bit = c
6616       // val = c
6617       if (size)
6618         outBitC (result);
6619       // if(bit | ...)
6620       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6621         genIfxJump (ifx, "c");
6622       goto release;
6623     }
6624
6625   if (sameRegs (AOP (result), AOP (left)))
6626     {
6627       /* if left is same as result */
6628       for (; size--; offset++)
6629         {
6630           if (AOP_TYPE (right) == AOP_LIT)
6631             {
6632               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6633                 continue;
6634               else if (IS_AOP_PREG (left))
6635                 {
6636                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6637                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6638                   aopPut (AOP (result), "a", offset);
6639                 }
6640               else
6641                 emitcode ("xrl", "%s,%s",
6642                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6643                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6644             }
6645           else
6646             {
6647               if (AOP_TYPE (left) == AOP_ACC)
6648                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6649               else
6650                 {
6651                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6652                   if (IS_AOP_PREG (left))
6653                     {
6654                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6655                       aopPut (AOP (result), "a", offset);
6656                     }
6657                   else
6658                     emitcode ("xrl", "%s,a",
6659                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6660                 }
6661             }
6662         }
6663     }
6664   else
6665     {
6666       // left & result in different registers
6667       if (AOP_TYPE (result) == AOP_CRY)
6668         {
6669           // result = bit
6670           // if(size), result in bit
6671           // if(!size && ifx), conditional oper: if(left ^ right)
6672           symbol *tlbl = newiTempLabel (NULL);
6673           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6674                   
6675           if (size)
6676             emitcode ("setb", "c");
6677           while (sizer--)
6678             {
6679               if ((AOP_TYPE (right) == AOP_LIT) &&
6680                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6681                 {
6682                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6683                 }
6684               else
6685                 {
6686                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6687                     emitcode ("xrl", "a,%s",
6688                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6689                   } else {
6690                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6691                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6692                       {
6693                           emitcode("mov", "b,a");
6694                           rOp = "b";
6695                       }
6696                         
6697                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6698                       emitcode ("xrl", "a,%s", rOp);                  
6699                   }
6700                 }
6701               emitcode ("jnz", "!tlabel", tlbl->key + 100);
6702               offset++;
6703             }
6704           if (size)
6705             {
6706               CLRC;
6707               emitcode ("", "!tlabeldef", tlbl->key + 100);
6708               outBitC (result);
6709             }
6710           else if (ifx)
6711             jmpTrueOrFalse (ifx, tlbl);
6712         }
6713       else
6714         {
6715         for (; (size--); offset++)
6716           {
6717             // normal case
6718             // result = left & right
6719             if (AOP_TYPE (right) == AOP_LIT)
6720               {
6721                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6722                   {
6723                     aopPut (AOP (result),
6724                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6725                             offset);
6726                     continue;
6727                   }
6728                 D (emitcode (";", "better literal XOR."););
6729                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6730                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6731                                                   FALSE, FALSE, FALSE));
6732               }
6733             else
6734               {
6735                 // faster than result <- left, anl result,right
6736                 // and better if result is SFR
6737                 if (AOP_TYPE (left) == AOP_ACC)
6738                   {
6739                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6740                                                      FALSE, FALSE, FALSE));
6741                   }
6742                 else
6743                   {
6744                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6745                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6746                       {
6747                           emitcode("mov", "b,a");
6748                           rOp = "b";
6749                       }
6750                         
6751                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6752                       emitcode ("xrl", "a,%s", rOp);
6753                   }
6754               }
6755             aopPut (AOP (result), "a", offset);
6756           }
6757         }
6758         
6759     }
6760
6761 release:
6762   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6763   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6764   freeAsmop (result, NULL, ic, TRUE);
6765 }
6766
6767 /*-----------------------------------------------------------------*/
6768 /* genInline - write the inline code out                           */
6769 /*-----------------------------------------------------------------*/
6770 static void
6771 genInline (iCode * ic)
6772 {
6773   char *buffer, *bp, *bp1;
6774
6775   D (emitcode (";", "genInline ");
6776     );
6777
6778   _G.inLine += (!options.asmpeep);
6779
6780   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6781   strcpy (buffer, IC_INLINE (ic));
6782
6783   /* emit each line as a code */
6784   while (*bp)
6785     {
6786       if (*bp == '\n')
6787         {
6788           *bp++ = '\0';
6789           emitcode (bp1, "");
6790           bp1 = bp;
6791         }
6792       else
6793         {
6794           if (*bp == ':')
6795             {
6796               bp++;
6797               *bp = '\0';
6798               bp++;
6799               emitcode (bp1, "");
6800               bp1 = bp;
6801             }
6802           else
6803             bp++;
6804         }
6805     }
6806   if (bp1 != bp)
6807     emitcode (bp1, "");
6808   /*     emitcode("",buffer); */
6809   _G.inLine -= (!options.asmpeep);
6810 }
6811
6812 /*-----------------------------------------------------------------*/
6813 /* genRRC - rotate right with carry                                */
6814 /*-----------------------------------------------------------------*/
6815 static void
6816 genRRC (iCode * ic)
6817 {
6818   operand *left, *result;
6819   int size, offset = 0;
6820   char *l;
6821
6822   D (emitcode (";", "genRRC ");
6823     );
6824
6825   /* rotate right with carry */
6826   left = IC_LEFT (ic);
6827   result = IC_RESULT (ic);
6828   aopOp (left, ic, FALSE, FALSE);
6829   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6830
6831   /* move it to the result */
6832   size = AOP_SIZE (result);
6833   offset = size - 1;
6834   CLRC;
6835
6836   _startLazyDPSEvaluation ();
6837   while (size--)
6838     {
6839       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6840       MOVA (l);
6841       emitcode ("rrc", "a");
6842       if (AOP_SIZE (result) > 1)
6843         aopPut (AOP (result), "a", offset--);
6844     }
6845   _endLazyDPSEvaluation ();
6846
6847   /* now we need to put the carry into the
6848      highest order byte of the result */
6849   if (AOP_SIZE (result) > 1)
6850     {
6851       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6852       MOVA (l);
6853     }
6854   emitcode ("mov", "acc.7,c");
6855   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6856   freeAsmop (left, NULL, ic, TRUE);
6857   freeAsmop (result, NULL, ic, TRUE);
6858 }
6859
6860 /*-----------------------------------------------------------------*/
6861 /* genRLC - generate code for rotate left with carry               */
6862 /*-----------------------------------------------------------------*/
6863 static void
6864 genRLC (iCode * ic)
6865 {
6866   operand *left, *result;
6867   int size, offset = 0;
6868   char *l;
6869
6870   D (emitcode (";", "genRLC ");
6871     );
6872
6873   /* rotate right with carry */
6874   left = IC_LEFT (ic);
6875   result = IC_RESULT (ic);
6876   aopOp (left, ic, FALSE, FALSE);
6877   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6878
6879   /* move it to the result */
6880   size = AOP_SIZE (result);
6881   offset = 0;
6882   if (size--)
6883     {
6884       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6885       MOVA (l);
6886       emitcode ("add", "a,acc");
6887       if (AOP_SIZE (result) > 1)
6888         {
6889           aopPut (AOP (result), "a", offset++);
6890         }
6891
6892       _startLazyDPSEvaluation ();
6893       while (size--)
6894         {
6895           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6896           MOVA (l);
6897           emitcode ("rlc", "a");
6898           if (AOP_SIZE (result) > 1)
6899             aopPut (AOP (result), "a", offset++);
6900         }
6901       _endLazyDPSEvaluation ();
6902     }
6903   /* now we need to put the carry into the
6904      highest order byte of the result */
6905   if (AOP_SIZE (result) > 1)
6906     {
6907       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6908       MOVA (l);
6909     }
6910   emitcode ("mov", "acc.0,c");
6911   aopPut (AOP (result), "a", 0);
6912   freeAsmop (left, NULL, ic, TRUE);
6913   freeAsmop (result, NULL, ic, TRUE);
6914 }
6915
6916 /*-----------------------------------------------------------------*/
6917 /* genGetHbit - generates code get highest order bit               */
6918 /*-----------------------------------------------------------------*/
6919 static void
6920 genGetHbit (iCode * ic)
6921 {
6922   operand *left, *result;
6923   left = IC_LEFT (ic);
6924   result = IC_RESULT (ic);
6925   aopOp (left, ic, FALSE, FALSE);
6926   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6927
6928   D (emitcode (";", "genGetHbit ");
6929     );
6930
6931   /* get the highest order byte into a */
6932   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6933   if (AOP_TYPE (result) == AOP_CRY)
6934     {
6935       emitcode ("rlc", "a");
6936       outBitC (result);
6937     }
6938   else
6939     {
6940       emitcode ("rl", "a");
6941       emitcode ("anl", "a,#1");
6942       outAcc (result);
6943     }
6944
6945
6946   freeAsmop (left, NULL, ic, TRUE);
6947   freeAsmop (result, NULL, ic, TRUE);
6948 }
6949
6950 /*-----------------------------------------------------------------*/
6951 /* AccRol - rotate left accumulator by known count                 */
6952 /*-----------------------------------------------------------------*/
6953 static void
6954 AccRol (int shCount)
6955 {
6956   shCount &= 0x0007;            // shCount : 0..7
6957
6958   switch (shCount)
6959     {
6960     case 0:
6961       break;
6962     case 1:
6963       emitcode ("rl", "a");
6964       break;
6965     case 2:
6966       emitcode ("rl", "a");
6967       emitcode ("rl", "a");
6968       break;
6969     case 3:
6970       emitcode ("swap", "a");
6971       emitcode ("rr", "a");
6972       break;
6973     case 4:
6974       emitcode ("swap", "a");
6975       break;
6976     case 5:
6977       emitcode ("swap", "a");
6978       emitcode ("rl", "a");
6979       break;
6980     case 6:
6981       emitcode ("rr", "a");
6982       emitcode ("rr", "a");
6983       break;
6984     case 7:
6985       emitcode ("rr", "a");
6986       break;
6987     }
6988 }
6989
6990 /*-----------------------------------------------------------------*/
6991 /* AccLsh - left shift accumulator by known count                  */
6992 /*-----------------------------------------------------------------*/
6993 static void
6994 AccLsh (int shCount)
6995 {
6996   if (shCount != 0)
6997     {
6998       if (shCount == 1)
6999         emitcode ("add", "a,acc");
7000       else if (shCount == 2)
7001         {
7002           emitcode ("add", "a,acc");
7003           emitcode ("add", "a,acc");
7004         }
7005       else
7006         {
7007           /* rotate left accumulator */
7008           AccRol (shCount);
7009           /* and kill the lower order bits */
7010           emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7011         }
7012     }
7013 }
7014
7015 /*-----------------------------------------------------------------*/
7016 /* AccRsh - right shift accumulator by known count                 */
7017 /*-----------------------------------------------------------------*/
7018 static void
7019 AccRsh (int shCount)
7020 {
7021   if (shCount != 0)
7022     {
7023       if (shCount == 1)
7024         {
7025           CLRC;
7026           emitcode ("rrc", "a");
7027         }
7028       else
7029         {
7030           /* rotate right accumulator */
7031           AccRol (8 - shCount);
7032           /* and kill the higher order bits */
7033           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7034         }
7035     }
7036 }
7037
7038 #ifdef BETTER_LITERAL_SHIFT
7039 /*-----------------------------------------------------------------*/
7040 /* AccSRsh - signed right shift accumulator by known count                 */
7041 /*-----------------------------------------------------------------*/
7042 static void
7043 AccSRsh (int shCount)
7044 {
7045   symbol *tlbl;
7046   if (shCount != 0)
7047     {
7048       if (shCount == 1)
7049         {
7050           emitcode ("mov", "c,acc.7");
7051           emitcode ("rrc", "a");
7052         }
7053       else if (shCount == 2)
7054         {
7055           emitcode ("mov", "c,acc.7");
7056           emitcode ("rrc", "a");
7057           emitcode ("mov", "c,acc.7");
7058           emitcode ("rrc", "a");
7059         }
7060       else
7061         {
7062           tlbl = newiTempLabel (NULL);
7063           /* rotate right accumulator */
7064           AccRol (8 - shCount);
7065           /* and kill the higher order bits */
7066           emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7067           emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7068           emitcode ("orl", "a,#!constbyte",
7069                     (unsigned char) ~SRMask[shCount]);
7070           emitcode ("", "!tlabeldef", tlbl->key + 100);
7071         }
7072     }
7073 }
7074 #endif
7075
7076 #ifdef BETTER_LITERAL_SHIFT
7077 /*-----------------------------------------------------------------*/
7078 /* shiftR1Left2Result - shift right one byte from left to result   */
7079 /*-----------------------------------------------------------------*/
7080 static void
7081 shiftR1Left2Result (operand * left, int offl,
7082                     operand * result, int offr,
7083                     int shCount, int sign)
7084 {
7085   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7086   /* shift right accumulator */
7087   if (sign)
7088     AccSRsh (shCount);
7089   else
7090     AccRsh (shCount);
7091   aopPut (AOP (result), "a", offr);
7092 }
7093 #endif
7094
7095 #ifdef BETTER_LITERAL_SHIFT
7096 /*-----------------------------------------------------------------*/
7097 /* shiftL1Left2Result - shift left one byte from left to result    */
7098 /*-----------------------------------------------------------------*/
7099 static void
7100 shiftL1Left2Result (operand * left, int offl,
7101                     operand * result, int offr, int shCount)
7102 {
7103   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7104   /* shift left accumulator */
7105   AccLsh (shCount);
7106   aopPut (AOP (result), "a", offr);
7107 }
7108 #endif
7109
7110 #ifdef BETTER_LITERAL_SHIFT
7111 /*-----------------------------------------------------------------*/
7112 /* movLeft2Result - move byte from left to result                  */
7113 /*-----------------------------------------------------------------*/
7114 static void
7115 movLeft2Result (operand * left, int offl,
7116                 operand * result, int offr, int sign)
7117 {
7118   char *l;
7119   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7120   {
7121       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
7122
7123       if (*l == '@' && (IS_AOP_PREG (result)))
7124       {
7125           emitcode ("mov", "a,%s", l);
7126           aopPut (AOP (result), "a", offr);
7127       }
7128       else
7129       {
7130           if (!sign)
7131           {
7132             aopPut (AOP (result), l, offr);
7133           }
7134           else
7135             {
7136               /* MSB sign in acc.7 ! */
7137               if (getDataSize (left) == offl + 1)
7138                 {
7139                   emitcode ("mov", "a,%s", l);
7140                   aopPut (AOP (result), "a", offr);
7141                 }
7142             }
7143       }
7144   }
7145 }
7146 #endif
7147
7148 #ifdef BETTER_LITERAL_SHIFT
7149 /*-----------------------------------------------------------------*/
7150 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
7151 /*-----------------------------------------------------------------*/
7152 static void
7153 AccAXRrl1 (char *x)
7154 {
7155   emitcode ("rrc", "a");
7156   emitcode ("xch", "a,%s", x);
7157   emitcode ("rrc", "a");
7158   emitcode ("xch", "a,%s", x);
7159 }
7160 #endif
7161
7162 #ifdef BETTER_LITERAL_SHIFT
7163 //REMOVE ME!!!
7164 /*-----------------------------------------------------------------*/
7165 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
7166 /*-----------------------------------------------------------------*/
7167 static void
7168 AccAXLrl1 (char *x)
7169 {
7170   emitcode ("xch", "a,%s", x);
7171   emitcode ("rlc", "a");
7172   emitcode ("xch", "a,%s", x);
7173   emitcode ("rlc", "a");
7174 }
7175 #endif
7176
7177 #ifdef BETTER_LITERAL_SHIFT
7178 /*-----------------------------------------------------------------*/
7179 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
7180 /*-----------------------------------------------------------------*/
7181 static void
7182 AccAXLsh1 (char *x)
7183 {
7184   emitcode ("xch", "a,%s", x);
7185   emitcode ("add", "a,acc");
7186   emitcode ("xch", "a,%s", x);
7187   emitcode ("rlc", "a");
7188 }
7189 #endif
7190
7191 #ifdef BETTER_LITERAL_SHIFT
7192 /*-----------------------------------------------------------------*/
7193 /* AccAXLsh - left shift a:x by known count (0..7)                 */
7194 /*-----------------------------------------------------------------*/
7195 static void
7196 AccAXLsh (char *x, int shCount)
7197 {
7198   switch (shCount)
7199     {
7200     case 0:
7201       break;
7202     case 1:
7203       AccAXLsh1 (x);
7204       break;
7205     case 2:
7206       AccAXLsh1 (x);
7207       AccAXLsh1 (x);
7208       break;
7209     case 3:
7210     case 4:
7211     case 5:                     // AAAAABBB:CCCCCDDD
7212
7213       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
7214
7215       emitcode ("anl", "a,#!constbyte",
7216                 SLMask[shCount]);       // BBB00000:CCCCCDDD
7217
7218       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
7219
7220       AccRol (shCount);         // DDDCCCCC:BBB00000
7221
7222       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
7223
7224       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
7225
7226       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
7227
7228       emitcode ("anl", "a,#!constbyte",
7229                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
7230
7231       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
7232
7233       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
7234
7235       break;
7236     case 6:                     // AAAAAABB:CCCCCCDD
7237       emitcode ("anl", "a,#!constbyte",
7238                 SRMask[shCount]);       // 000000BB:CCCCCCDD
7239       emitcode ("mov", "c,acc.0");      // c = B
7240       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
7241 #if 0
7242       AccAXRrl1 (x);            // BCCCCCCD:D000000B
7243       AccAXRrl1 (x);            // BBCCCCCC:DD000000
7244 #else
7245       emitcode("rrc","a"); 
7246       emitcode("xch","a,%s", x); 
7247       emitcode("rrc","a"); 
7248       emitcode("mov","c,acc.0"); //<< get correct bit 
7249       emitcode("xch","a,%s", x); 
7250
7251       emitcode("rrc","a"); 
7252       emitcode("xch","a,%s", x); 
7253       emitcode("rrc","a"); 
7254       emitcode("xch","a,%s", x); 
7255 #endif
7256       break;
7257     case 7:                     // a:x <<= 7
7258
7259       emitcode ("anl", "a,#!constbyte",
7260                 SRMask[shCount]);       // 0000000B:CCCCCCCD
7261
7262       emitcode ("mov", "c,acc.0");      // c = B
7263
7264       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
7265
7266       AccAXRrl1 (x);            // BCCCCCCC:D0000000
7267
7268       break;
7269     default:
7270       break;
7271     }
7272 }
7273 #endif
7274
7275 #ifdef BETTER_LITERAL_SHIFT
7276 //REMOVE ME!!!
7277 /*-----------------------------------------------------------------*/
7278 /* AccAXRsh - right shift a:x known count (0..7)                   */
7279 /*-----------------------------------------------------------------*/
7280 static void
7281 AccAXRsh (char *x, int shCount)
7282 {
7283   switch (shCount)
7284     {
7285     case 0:
7286       break;
7287     case 1:
7288       CLRC;
7289       AccAXRrl1 (x);            // 0->a:x
7290
7291       break;
7292     case 2:
7293       CLRC;
7294       AccAXRrl1 (x);            // 0->a:x
7295
7296       CLRC;
7297       AccAXRrl1 (x);            // 0->a:x
7298
7299       break;
7300     case 3:
7301     case 4:
7302     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7303
7304       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7305
7306       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7307
7308       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7309
7310       emitcode ("anl", "a,#!constbyte",
7311                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7312
7313       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7314
7315       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7316
7317       emitcode ("anl", "a,#!constbyte",
7318                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7319
7320       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7321
7322       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7323
7324       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7325
7326       break;
7327     case 6:                     // AABBBBBB:CCDDDDDD
7328
7329       emitcode ("mov", "c,acc.7");
7330       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7331
7332       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7333
7334       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7335
7336       emitcode ("anl", "a,#!constbyte",
7337                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7338
7339       break;
7340     case 7:                     // ABBBBBBB:CDDDDDDD
7341
7342       emitcode ("mov", "c,acc.7");      // c = A
7343
7344       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7345
7346       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7347
7348       emitcode ("anl", "a,#!constbyte",
7349                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7350
7351       break;
7352     default:
7353       break;
7354     }
7355 }
7356 #endif
7357
7358 #ifdef BETTER_LITERAL_SHIFT
7359 /*-----------------------------------------------------------------*/
7360 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7361 /*-----------------------------------------------------------------*/
7362 static void
7363 AccAXRshS (char *x, int shCount)
7364 {
7365   symbol *tlbl;
7366   switch (shCount)
7367     {
7368     case 0:
7369       break;
7370     case 1:
7371       emitcode ("mov", "c,acc.7");
7372       AccAXRrl1 (x);            // s->a:x
7373
7374       break;
7375     case 2:
7376       emitcode ("mov", "c,acc.7");
7377       AccAXRrl1 (x);            // s->a:x
7378
7379       emitcode ("mov", "c,acc.7");
7380       AccAXRrl1 (x);            // s->a:x
7381
7382       break;
7383     case 3:
7384     case 4:
7385     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7386
7387       tlbl = newiTempLabel (NULL);
7388       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7389
7390       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7391
7392       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7393
7394       emitcode ("anl", "a,#!constbyte",
7395                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7396
7397       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7398
7399       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7400
7401       emitcode ("anl", "a,#!constbyte",
7402                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7403
7404       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7405
7406       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7407
7408       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7409
7410       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7411       emitcode ("orl", "a,#!constbyte",
7412                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7413
7414       emitcode ("", "!tlabeldef", tlbl->key + 100);
7415       break;                    // SSSSAAAA:BBBCCCCC
7416
7417     case 6:                     // AABBBBBB:CCDDDDDD
7418
7419       tlbl = newiTempLabel (NULL);
7420       emitcode ("mov", "c,acc.7");
7421       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7422
7423       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7424
7425       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7426
7427       emitcode ("anl", "a,#!constbyte",
7428                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7429
7430       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7431       emitcode ("orl", "a,#!constbyte",
7432                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7433
7434       emitcode ("", "!tlabeldef", tlbl->key + 100);
7435       break;
7436     case 7:                     // ABBBBBBB:CDDDDDDD
7437
7438       tlbl = newiTempLabel (NULL);
7439       emitcode ("mov", "c,acc.7");      // c = A
7440
7441       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7442
7443       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7444
7445       emitcode ("anl", "a,#!constbyte",
7446                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7447
7448       emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7449       emitcode ("orl", "a,#!constbyte",
7450                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7451
7452       emitcode ("", "!tlabeldef", tlbl->key + 100);
7453       break;
7454     default:
7455       break;
7456     }
7457 }
7458 #endif
7459
7460 #ifdef BETTER_LITERAL_SHIFT
7461 static void
7462 _loadLeftIntoAx(char    **lsb, 
7463                 operand *left, 
7464                 operand *result,
7465                 int     offl,
7466                 int     offr)
7467 {
7468   // Get the initial value from left into a pair of registers.
7469   // MSB must be in A, LSB can be any register.
7470   //
7471   // If the result is held in registers, it is an optimization
7472   // if the LSB can be held in the register which will hold the,
7473   // result LSB since this saves us from having to copy it into
7474   // the result following AccAXLsh.
7475   //
7476   // If the result is addressed indirectly, this is not a gain.
7477   if (AOP_NEEDSACC(result))
7478   {
7479        char *leftByte;
7480        
7481        _startLazyDPSEvaluation();
7482       if (AOP_TYPE(left) == AOP_DPTR2)
7483        {
7484            // Get MSB in A.
7485            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7486            // get LSB in DP2_RESULT_REG.
7487            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7488            assert(!strcmp(leftByte, DP2_RESULT_REG));
7489        }
7490        else
7491        {
7492            // get LSB into DP2_RESULT_REG
7493            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7494            if (strcmp(leftByte, DP2_RESULT_REG))
7495            {
7496                TR_AP("#7");
7497                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7498            }
7499            // And MSB in A.
7500            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7501            assert(strcmp(leftByte, DP2_RESULT_REG));
7502            MOVA(leftByte);
7503        }
7504        _endLazyDPSEvaluation();
7505        *lsb = DP2_RESULT_REG;
7506   }
7507   else
7508   {
7509       if (sameRegs (AOP (result), AOP (left)) &&
7510         ((offl + MSB16) == offr))
7511       {
7512           /* don't crash result[offr] */
7513           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7514           emitcode ("xch", "a,%s", 
7515                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7516       }
7517       else
7518       {
7519           movLeft2Result (left, offl, result, offr, 0);
7520           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7521       }
7522       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7523       assert(strcmp(*lsb,"a"));      
7524   }
7525 }
7526
7527 static void
7528 _storeAxResults(char    *lsb,
7529                 operand *result,
7530                 int     offr)
7531 {
7532   _startLazyDPSEvaluation();
7533   if (AOP_NEEDSACC(result))
7534   {
7535       /* We have to explicitly update the result LSB.
7536        */
7537       emitcode("xch","a,%s", lsb);
7538       aopPut(AOP(result), "a", offr);
7539       emitcode("mov","a,%s", lsb);
7540   }
7541   if (getDataSize (result) > 1)
7542   {
7543       aopPut (AOP (result), "a", offr + MSB16);
7544   }
7545   _endLazyDPSEvaluation();
7546 }
7547
7548 /*-----------------------------------------------------------------*/
7549 /* shiftL2Left2Result - shift left two bytes from left to result   */
7550 /*-----------------------------------------------------------------*/
7551 static void
7552 shiftL2Left2Result (operand * left, int offl,
7553                     operand * result, int offr, int shCount)
7554 {
7555   char *lsb;
7556
7557   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7558   
7559   AccAXLsh (lsb, shCount);
7560   
7561   _storeAxResults(lsb, result, offr);
7562 }
7563 #endif
7564
7565 #ifdef BETTER_LITERAL_SHIFT
7566 /*-----------------------------------------------------------------*/
7567 /* shiftR2Left2Result - shift right two bytes from left to result  */
7568 /*-----------------------------------------------------------------*/
7569 static void
7570 shiftR2Left2Result (operand * left, int offl,
7571                     operand * result, int offr,
7572                     int shCount, int sign)
7573 {
7574   char *lsb;
7575   
7576   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7577   
7578   /* a:x >> shCount (x = lsb(result)) */
7579   if (sign)
7580   {
7581      AccAXRshS(lsb, shCount);
7582   }
7583   else
7584   {
7585     AccAXRsh(lsb, shCount);
7586   }
7587   
7588   _storeAxResults(lsb, result, offr);
7589 }
7590 #endif
7591
7592 #if 0
7593 //REMOVE ME!!!
7594 /*-----------------------------------------------------------------*/
7595 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7596 /*-----------------------------------------------------------------*/
7597 static void
7598 shiftLLeftOrResult (operand * left, int offl,
7599                     operand * result, int offr, int shCount)
7600 {
7601   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7602   /* shift left accumulator */
7603   AccLsh (shCount);
7604   /* or with result */
7605   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7606   /* back to result */
7607   aopPut (AOP (result), "a", offr);
7608 }
7609 #endif
7610
7611 #if 0
7612 //REMOVE ME!!!
7613 /*-----------------------------------------------------------------*/
7614 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7615 /*-----------------------------------------------------------------*/
7616 static void
7617 shiftRLeftOrResult (operand * left, int offl,
7618                     operand * result, int offr, int shCount)
7619 {
7620   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7621   /* shift right accumulator */
7622   AccRsh (shCount);
7623   /* or with result */
7624   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7625   /* back to result */
7626   aopPut (AOP (result), "a", offr);
7627 }
7628 #endif
7629
7630 #ifdef BETTER_LITERAL_SHIFT
7631 /*-----------------------------------------------------------------*/
7632 /* genlshOne - left shift a one byte quantity by known count       */
7633 /*-----------------------------------------------------------------*/
7634 static void
7635 genlshOne (operand * result, operand * left, int shCount)
7636 {
7637   D (emitcode (";", "genlshOne "););
7638   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7639 }
7640 #endif
7641
7642 #ifdef BETTER_LITERAL_SHIFT
7643 /*-----------------------------------------------------------------*/
7644 /* genlshTwo - left shift two bytes by known amount != 0           */
7645 /*-----------------------------------------------------------------*/
7646 static void
7647 genlshTwo (operand * result, operand * left, int shCount)
7648 {
7649   int size;
7650
7651   D (emitcode (";", "genlshTwo "););
7652
7653   size = getDataSize (result);
7654
7655   /* if shCount >= 8 */
7656   if (shCount >= 8)
7657   {
7658       shCount -= 8;
7659
7660       _startLazyDPSEvaluation();
7661
7662       if (size > 1)
7663         {
7664           if (shCount)
7665           {
7666             _endLazyDPSEvaluation();
7667             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7668             aopPut (AOP (result), zero, LSB);       
7669           }
7670           else
7671           {
7672             movLeft2Result (left, LSB, result, MSB16, 0);
7673             aopPut (AOP (result), zero, LSB);
7674             _endLazyDPSEvaluation();
7675           }
7676         }
7677         else
7678         {
7679           aopPut (AOP (result), zero, LSB);
7680           _endLazyDPSEvaluation();
7681         }
7682   }
7683
7684   /*  1 <= shCount <= 7 */
7685   else
7686     {
7687       if (size == 1)
7688       {
7689         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7690       }
7691       else
7692       {
7693         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7694       }
7695     }
7696 }
7697 #endif
7698
7699 #if 0
7700 //REMOVE ME!!!
7701 /*-----------------------------------------------------------------*/
7702 /* shiftLLong - shift left one long from left to result            */
7703 /* offl = LSB or MSB16                                             */
7704 /*-----------------------------------------------------------------*/
7705 static void
7706 shiftLLong (operand * left, operand * result, int offr)
7707 {
7708   char *l;
7709   int size = AOP_SIZE (result);
7710
7711   if (size >= LSB + offr)
7712     {
7713       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7714       MOVA (l);
7715       emitcode ("add", "a,acc");
7716       if (sameRegs (AOP (left), AOP (result)) &&
7717           size >= MSB16 + offr && offr != LSB)
7718         emitcode ("xch", "a,%s",
7719                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7720       else
7721         aopPut (AOP (result), "a", LSB + offr);
7722     }
7723
7724   if (size >= MSB16 + offr)
7725     {
7726       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7727         {
7728           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7729           MOVA (l);
7730         }
7731       emitcode ("rlc", "a");
7732       if (sameRegs (AOP (left), AOP (result)) &&
7733           size >= MSB24 + offr && offr != LSB)
7734         emitcode ("xch", "a,%s",
7735                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7736       else
7737         aopPut (AOP (result), "a", MSB16 + offr);
7738     }
7739
7740   if (size >= MSB24 + offr)
7741     {
7742       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7743         {
7744           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7745           MOVA (l);
7746         }
7747       emitcode ("rlc", "a");
7748       if (sameRegs (AOP (left), AOP (result)) &&
7749           size >= MSB32 + offr && offr != LSB)
7750         emitcode ("xch", "a,%s",
7751                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7752       else
7753         aopPut (AOP (result), "a", MSB24 + offr);
7754     }
7755
7756   if (size > MSB32 + offr)
7757     {
7758       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7759         {
7760           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7761           MOVA (l);
7762         }
7763       emitcode ("rlc", "a");
7764       aopPut (AOP (result), "a", MSB32 + offr);
7765     }
7766   if (offr != LSB)
7767     aopPut (AOP (result), zero, LSB);
7768 }
7769 #endif
7770
7771 #if 0
7772 //REMOVE ME!!!
7773 /*-----------------------------------------------------------------*/
7774 /* genlshFour - shift four byte by a known amount != 0             */
7775 /*-----------------------------------------------------------------*/
7776 static void
7777 genlshFour (operand * result, operand * left, int shCount)
7778 {
7779   int size;
7780
7781   D (emitcode (";", "genlshFour ");
7782     );
7783
7784   size = AOP_SIZE (result);
7785
7786   /* if shifting more that 3 bytes */
7787   if (shCount >= 24)
7788     {
7789       shCount -= 24;
7790       if (shCount)
7791         /* lowest order of left goes to the highest
7792            order of the destination */
7793         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7794       else
7795         movLeft2Result (left, LSB, result, MSB32, 0);
7796       aopPut (AOP (result), zero, LSB);
7797       aopPut (AOP (result), zero, MSB16);
7798       aopPut (AOP (result), zero, MSB24);
7799       return;
7800     }
7801
7802   /* more than two bytes */
7803   else if (shCount >= 16)
7804     {
7805       /* lower order two bytes goes to higher order two bytes */
7806       shCount -= 16;
7807       /* if some more remaining */
7808       if (shCount)
7809         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7810       else
7811         {
7812           movLeft2Result (left, MSB16, result, MSB32, 0);
7813           movLeft2Result (left, LSB, result, MSB24, 0);
7814         }
7815       aopPut (AOP (result), zero, MSB16);
7816       aopPut (AOP (result), zero, LSB);
7817       return;
7818     }
7819
7820   /* if more than 1 byte */
7821   else if (shCount >= 8)
7822     {
7823       /* lower order three bytes goes to higher order  three bytes */
7824       shCount -= 8;
7825       if (size == 2)
7826         {
7827           if (shCount)
7828             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7829           else
7830             movLeft2Result (left, LSB, result, MSB16, 0);
7831         }
7832       else
7833         {                       /* size = 4 */
7834           if (shCount == 0)
7835             {
7836               movLeft2Result (left, MSB24, result, MSB32, 0);
7837               movLeft2Result (left, MSB16, result, MSB24, 0);
7838               movLeft2Result (left, LSB, result, MSB16, 0);
7839               aopPut (AOP (result), zero, LSB);
7840             }
7841           else if (shCount == 1)
7842             shiftLLong (left, result, MSB16);
7843           else
7844             {
7845               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7846               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7847               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7848               aopPut (AOP (result), zero, LSB);
7849             }
7850         }
7851     }
7852
7853   /* 1 <= shCount <= 7 */
7854   else if (shCount <= 2)
7855     {
7856       shiftLLong (left, result, LSB);
7857       if (shCount == 2)
7858         shiftLLong (result, result, LSB);
7859     }
7860   /* 3 <= shCount <= 7, optimize */
7861   else
7862     {
7863       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7864       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7865       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7866     }
7867 }
7868 #endif
7869
7870 #ifdef BETTER_LITERAL_SHIFT
7871 /*-----------------------------------------------------------------*/
7872 /* genLeftShiftLiteral - left shifting by known count              */
7873 /*-----------------------------------------------------------------*/
7874 static bool
7875 genLeftShiftLiteral (operand * left,
7876                      operand * right,
7877                      operand * result,
7878                      iCode * ic)
7879 {
7880   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7881   int size;
7882
7883   size = getSize (operandType (result));
7884
7885   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7886
7887   /* We only handle certain easy cases so far. */
7888   if ((shCount != 0)
7889    && (shCount < (size * 8))
7890    && (size != 1)
7891    && (size != 2))
7892   {
7893       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7894       return FALSE;
7895   }
7896
7897   freeAsmop (right, NULL, ic, TRUE);
7898
7899   aopOp(left, ic, FALSE, FALSE);
7900   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7901
7902 #if 0 // debug spew
7903   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7904   {
7905         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7906         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7907         {
7908            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7909         }
7910   }
7911   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7912   {
7913         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7914         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7915         {
7916            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7917         }       
7918   }  
7919 #endif
7920   
7921 #if VIEW_SIZE
7922   emitcode ("; shift left ", "result %d, left %d", size,
7923             AOP_SIZE (left));
7924 #endif
7925
7926   /* I suppose that the left size >= result size */
7927   if (shCount == 0)
7928   {
7929         _startLazyDPSEvaluation();
7930         while (size--)
7931         {
7932           movLeft2Result (left, size, result, size, 0);
7933         }
7934         _endLazyDPSEvaluation();
7935   }
7936   else if (shCount >= (size * 8))
7937   {
7938     _startLazyDPSEvaluation();
7939     while (size--)
7940     {
7941       aopPut (AOP (result), zero, size);
7942     }
7943     _endLazyDPSEvaluation();
7944   }
7945   else
7946   {
7947       switch (size)
7948         {
7949         case 1:
7950           genlshOne (result, left, shCount);
7951           break;
7952
7953         case 2:
7954           genlshTwo (result, left, shCount);
7955           break;
7956 #if 0
7957         case 4:
7958           genlshFour (result, left, shCount);
7959           break;
7960 #endif
7961         default:
7962           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7963           break;
7964         }
7965     }
7966   freeAsmop (left, NULL, ic, TRUE);
7967   freeAsmop (result, NULL, ic, TRUE);
7968   return TRUE;
7969 }
7970 #endif
7971
7972 /*-----------------------------------------------------------------*/
7973 /* genLeftShift - generates code for left shifting                 */
7974 /*-----------------------------------------------------------------*/
7975 static void
7976 genLeftShift (iCode * ic)
7977 {
7978   operand *left, *right, *result;
7979   int size, offset;
7980   char *l;
7981   symbol *tlbl, *tlbl1;
7982
7983   D (emitcode (";", "genLeftShift "););
7984
7985   right = IC_RIGHT (ic);
7986   left = IC_LEFT (ic);
7987   result = IC_RESULT (ic);
7988
7989   aopOp (right, ic, FALSE, FALSE);
7990
7991
7992 #ifdef BETTER_LITERAL_SHIFT
7993   /* if the shift count is known then do it
7994      as efficiently as possible */
7995   if (AOP_TYPE (right) == AOP_LIT)
7996     {
7997       if (genLeftShiftLiteral (left, right, result, ic))
7998       {
7999         return;
8000       }
8001     }
8002 #endif
8003
8004   /* shift count is unknown then we have to form
8005      a loop get the loop count in B : Note: we take
8006      only the lower order byte since shifting
8007      more that 32 bits make no sense anyway, ( the
8008      largest size of an object can be only 32 bits ) */
8009
8010   if (AOP_TYPE (right) == AOP_LIT)
8011   {
8012       /* Really should be handled by genLeftShiftLiteral,
8013        * but since I'm too lazy to fix that today, at least we can make
8014        * some small improvement.
8015        */
8016        emitcode("mov", "b,#!constbyte",
8017                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8018   }
8019   else
8020   {
8021         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8022         emitcode ("inc", "b");
8023   }
8024   freeAsmop (right, NULL, ic, TRUE);
8025   aopOp (left, ic, FALSE, FALSE);
8026   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8027
8028   /* now move the left to the result if they are not the
8029      same */
8030   if (!sameRegs (AOP (left), AOP (result)) &&
8031       AOP_SIZE (result) > 1)
8032     {
8033
8034       size = AOP_SIZE (result);
8035       offset = 0;
8036       _startLazyDPSEvaluation ();
8037       while (size--)
8038         {
8039           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8040           if (*l == '@' && (IS_AOP_PREG (result)))
8041             {
8042
8043               emitcode ("mov", "a,%s", l);
8044               aopPut (AOP (result), "a", offset);
8045             }
8046           else
8047             aopPut (AOP (result), l, offset);
8048           offset++;
8049         }
8050       _endLazyDPSEvaluation ();
8051     }
8052
8053   tlbl = newiTempLabel (NULL);
8054   size = AOP_SIZE (result);
8055   offset = 0;
8056   tlbl1 = newiTempLabel (NULL);
8057
8058   /* if it is only one byte then */
8059   if (size == 1)
8060     {
8061       symbol *tlbl1 = newiTempLabel (NULL);
8062
8063       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8064       MOVA (l);
8065       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8066       emitcode ("", "!tlabeldef", tlbl->key + 100);
8067       emitcode ("add", "a,acc");
8068       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8069       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8070       aopPut (AOP (result), "a", 0);
8071       goto release;
8072     }
8073
8074   reAdjustPreg (AOP (result));
8075
8076   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8077   emitcode ("", "!tlabeldef", tlbl->key + 100);
8078   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8079   MOVA (l);
8080   emitcode ("add", "a,acc");
8081   aopPut (AOP (result), "a", offset++);
8082   _startLazyDPSEvaluation ();
8083   while (--size)
8084     {
8085       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8086       MOVA (l);
8087       emitcode ("rlc", "a");
8088       aopPut (AOP (result), "a", offset++);
8089     }
8090   _endLazyDPSEvaluation ();
8091   reAdjustPreg (AOP (result));
8092
8093   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8094   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8095 release:
8096   freeAsmop (left, NULL, ic, TRUE);
8097   freeAsmop (result, NULL, ic, TRUE);
8098 }
8099
8100 #ifdef BETTER_LITERAL_SHIFT
8101 /*-----------------------------------------------------------------*/
8102 /* genrshOne - right shift a one byte quantity by known count      */
8103 /*-----------------------------------------------------------------*/
8104 static void
8105 genrshOne (operand * result, operand * left,
8106            int shCount, int sign)
8107 {
8108   D (emitcode (";", "genrshOne"););
8109   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8110 }
8111 #endif
8112
8113 #ifdef BETTER_LITERAL_SHIFT
8114 /*-----------------------------------------------------------------*/
8115 /* genrshTwo - right shift two bytes by known amount != 0          */
8116 /*-----------------------------------------------------------------*/
8117 static void
8118 genrshTwo (operand * result, operand * left,
8119            int shCount, int sign)
8120 {
8121   D (emitcode (";", "genrshTwo"););
8122
8123   /* if shCount >= 8 */
8124   if (shCount >= 8)
8125     {
8126       shCount -= 8;
8127       _startLazyDPSEvaluation();
8128       if (shCount)
8129       {
8130         shiftR1Left2Result (left, MSB16, result, LSB,
8131                             shCount, sign);
8132       }                     
8133       else
8134       {
8135         movLeft2Result (left, MSB16, result, LSB, sign);
8136       }
8137       addSign (result, MSB16, sign);
8138       _endLazyDPSEvaluation();
8139     }
8140
8141   /*  1 <= shCount <= 7 */
8142   else
8143   {
8144     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8145   }
8146 }
8147 #endif
8148
8149 #if 0
8150 //REMOVE ME!!!
8151 /*-----------------------------------------------------------------*/
8152 /* shiftRLong - shift right one long from left to result           */
8153 /* offl = LSB or MSB16                                             */
8154 /*-----------------------------------------------------------------*/
8155 static void
8156 shiftRLong (operand * left, int offl,
8157             operand * result, int sign)
8158 {
8159   int isSameRegs=sameRegs(AOP(left),AOP(result));
8160
8161   if (isSameRegs && offl>1) {
8162     // we are in big trouble, but this shouldn't happen
8163     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8164   }
8165
8166   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
8167   
8168   if (offl==MSB16) {
8169     // shift is > 8
8170     if (sign) {
8171       emitcode ("rlc", "a");
8172       emitcode ("subb", "a,acc");
8173       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
8174     } else {
8175       aopPut (AOP(result), zero, MSB32);
8176     }
8177   }
8178
8179   if (!sign) {
8180     emitcode ("clr", "c");
8181   } else {
8182     emitcode ("mov", "c,acc.7");
8183   }
8184
8185   emitcode ("rrc", "a");
8186
8187   if (isSameRegs && offl==MSB16) {
8188     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
8189   } else {
8190     aopPut (AOP (result), "a", MSB32);
8191     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
8192   }
8193
8194   emitcode ("rrc", "a");
8195   if (isSameRegs && offl==1) {
8196     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
8197   } else {
8198     aopPut (AOP (result), "a", MSB24);
8199     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
8200   }
8201   emitcode ("rrc", "a");
8202   aopPut (AOP (result), "a", MSB16 - offl);
8203
8204   if (offl == LSB)
8205     {
8206       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
8207       emitcode ("rrc", "a");
8208       aopPut (AOP (result), "a", LSB);
8209     }
8210 }
8211 #endif
8212
8213 #if 0
8214 //REMOVE ME!!!
8215 /*-----------------------------------------------------------------*/
8216 /* genrshFour - shift four byte by a known amount != 0             */
8217 /*-----------------------------------------------------------------*/
8218 static void
8219 genrshFour (operand * result, operand * left,
8220             int shCount, int sign)
8221 {
8222   D (emitcode (";", "genrshFour");
8223     );
8224
8225   /* if shifting more that 3 bytes */
8226   if (shCount >= 24)
8227     {
8228       shCount -= 24;
8229       if (shCount)
8230         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8231       else
8232         movLeft2Result (left, MSB32, result, LSB, sign);
8233       addSign (result, MSB16, sign);
8234     }
8235   else if (shCount >= 16)
8236     {
8237       shCount -= 16;
8238       if (shCount)
8239         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8240       else
8241         {
8242           movLeft2Result (left, MSB24, result, LSB, 0);
8243           movLeft2Result (left, MSB32, result, MSB16, sign);
8244         }
8245       addSign (result, MSB24, sign);
8246     }
8247   else if (shCount >= 8)
8248     {
8249       shCount -= 8;
8250       if (shCount == 1)
8251         shiftRLong (left, MSB16, result, sign);
8252       else if (shCount == 0)
8253         {
8254           movLeft2Result (left, MSB16, result, LSB, 0);
8255           movLeft2Result (left, MSB24, result, MSB16, 0);
8256           movLeft2Result (left, MSB32, result, MSB24, sign);
8257           addSign (result, MSB32, sign);
8258         }
8259       else
8260         {
8261           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8262           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8263           /* the last shift is signed */
8264           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8265           addSign (result, MSB32, sign);
8266         }
8267     }
8268   else
8269     {                           /* 1 <= shCount <= 7 */
8270       if (shCount <= 2)
8271         {
8272           shiftRLong (left, LSB, result, sign);
8273           if (shCount == 2)
8274             shiftRLong (result, LSB, result, sign);
8275         }
8276       else
8277         {
8278           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8279           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8280           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8281         }
8282     }
8283 }
8284 #endif
8285
8286 #ifdef BETTER_LITERAL_SHIFT
8287 /*-----------------------------------------------------------------*/
8288 /* genRightShiftLiteral - right shifting by known count            */
8289 /*-----------------------------------------------------------------*/
8290 static bool
8291 genRightShiftLiteral (operand * left,
8292                       operand * right,
8293                       operand * result,
8294                       iCode * ic,
8295                       int sign)
8296 {
8297   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8298   int size;
8299
8300   size = getSize (operandType (result));
8301
8302   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8303
8304   /* We only handle certain easy cases so far. */
8305   if ((shCount != 0)
8306    && (shCount < (size * 8))
8307    && (size != 1)
8308    && (size != 2))
8309   {
8310       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8311       return FALSE;
8312   }
8313
8314   freeAsmop (right, NULL, ic, TRUE);
8315
8316   aopOp (left, ic, FALSE, FALSE);
8317   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8318
8319 #if VIEW_SIZE
8320   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8321             AOP_SIZE (left));
8322 #endif
8323
8324   /* test the LEFT size !!! */
8325
8326   /* I suppose that the left size >= result size */
8327   if (shCount == 0)
8328   {
8329       size = getDataSize (result);
8330       _startLazyDPSEvaluation();
8331       while (size--)
8332       {
8333         movLeft2Result (left, size, result, size, 0);
8334       }
8335       _endLazyDPSEvaluation();
8336   }
8337   else if (shCount >= (size * 8))
8338     {
8339       if (sign)
8340       {
8341         /* get sign in acc.7 */
8342         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8343       }
8344       addSign (result, LSB, sign);
8345     }
8346   else
8347     {
8348       switch (size)
8349         {
8350         case 1:
8351           genrshOne (result, left, shCount, sign);
8352           break;
8353
8354         case 2:
8355           genrshTwo (result, left, shCount, sign);
8356           break;
8357 #if 0
8358         case 4:
8359           genrshFour (result, left, shCount, sign);
8360           break;
8361 #endif    
8362         default:
8363           break;
8364         }
8365
8366       freeAsmop (left, NULL, ic, TRUE);
8367       freeAsmop (result, NULL, ic, TRUE);
8368     }
8369     return TRUE;
8370 }
8371 #endif
8372
8373 /*-----------------------------------------------------------------*/
8374 /* genSignedRightShift - right shift of signed number              */
8375 /*-----------------------------------------------------------------*/
8376 static void
8377 genSignedRightShift (iCode * ic)
8378 {
8379   operand *right, *left, *result;
8380   int size, offset;
8381   char *l;
8382   symbol *tlbl, *tlbl1;
8383
8384   D (emitcode (";", "genSignedRightShift "););
8385
8386   /* we do it the hard way put the shift count in b
8387      and loop thru preserving the sign */
8388
8389   right = IC_RIGHT (ic);
8390   left = IC_LEFT (ic);
8391   result = IC_RESULT (ic);
8392
8393   aopOp (right, ic, FALSE, FALSE);
8394
8395 #ifdef BETTER_LITERAL_SHIFT
8396   if (AOP_TYPE (right) == AOP_LIT)
8397     {
8398       if (genRightShiftLiteral (left, right, result, ic, 1))
8399       {
8400         return;
8401       }
8402     }
8403 #endif
8404   /* shift count is unknown then we have to form
8405      a loop get the loop count in B : Note: we take
8406      only the lower order byte since shifting
8407      more that 32 bits make no sense anyway, ( the
8408      largest size of an object can be only 32 bits ) */
8409
8410   if (AOP_TYPE (right) == AOP_LIT)
8411   {
8412       /* Really should be handled by genRightShiftLiteral,
8413        * but since I'm too lazy to fix that today, at least we can make
8414        * some small improvement.
8415        */
8416        emitcode("mov", "b,#!constbyte",
8417                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8418   }
8419   else
8420   {
8421         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8422         emitcode ("inc", "b");
8423   }
8424   freeAsmop (right, NULL, ic, TRUE);
8425   aopOp (left, ic, FALSE, FALSE);
8426   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8427
8428   /* now move the left to the result if they are not the
8429      same */
8430   if (!sameRegs (AOP (left), AOP (result)) &&
8431       AOP_SIZE (result) > 1)
8432     {
8433
8434       size = AOP_SIZE (result);
8435       offset = 0;
8436       _startLazyDPSEvaluation ();
8437       while (size--)
8438         {
8439           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8440           if (*l == '@' && IS_AOP_PREG (result))
8441             {
8442
8443               emitcode ("mov", "a,%s", l);
8444               aopPut (AOP (result), "a", offset);
8445             }
8446           else
8447             aopPut (AOP (result), l, offset);
8448           offset++;
8449         }
8450       _endLazyDPSEvaluation ();
8451     }
8452
8453   /* mov the highest order bit to OVR */
8454   tlbl = newiTempLabel (NULL);
8455   tlbl1 = newiTempLabel (NULL);
8456
8457   size = AOP_SIZE (result);
8458   offset = size - 1;
8459   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8460   emitcode ("rlc", "a");
8461   emitcode ("mov", "ov,c");
8462   /* if it is only one byte then */
8463   if (size == 1)
8464     {
8465       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8466       MOVA (l);
8467       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8468       emitcode ("", "!tlabeldef", tlbl->key + 100);
8469       emitcode ("mov", "c,ov");
8470       emitcode ("rrc", "a");
8471       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8472       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8473       aopPut (AOP (result), "a", 0);
8474       goto release;
8475     }
8476
8477   reAdjustPreg (AOP (result));
8478   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8479   emitcode ("", "!tlabeldef", tlbl->key + 100);
8480   emitcode ("mov", "c,ov");
8481   _startLazyDPSEvaluation ();
8482   while (size--)
8483     {
8484       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8485       MOVA (l);
8486       emitcode ("rrc", "a");
8487       aopPut (AOP (result), "a", offset--);
8488     }
8489   _endLazyDPSEvaluation ();
8490   reAdjustPreg (AOP (result));
8491   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8492   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8493
8494 release:
8495   freeAsmop (left, NULL, ic, TRUE);
8496   freeAsmop (result, NULL, ic, TRUE);
8497 }
8498
8499 /*-----------------------------------------------------------------*/
8500 /* genRightShift - generate code for right shifting                */
8501 /*-----------------------------------------------------------------*/
8502 static void
8503 genRightShift (iCode * ic)
8504 {
8505   operand *right, *left, *result;
8506   sym_link *retype;
8507   int size, offset;
8508   char *l;
8509   symbol *tlbl, *tlbl1;
8510
8511   D (emitcode (";", "genRightShift "););
8512
8513   /* if signed then we do it the hard way preserve the
8514      sign bit moving it inwards */
8515   retype = getSpec (operandType (IC_RESULT (ic)));
8516
8517   if (!SPEC_USIGN (retype))
8518     {
8519       genSignedRightShift (ic);
8520       return;
8521     }
8522
8523   /* signed & unsigned types are treated the same : i.e. the
8524      signed is NOT propagated inwards : quoting from the
8525      ANSI - standard : "for E1 >> E2, is equivalent to division
8526      by 2**E2 if unsigned or if it has a non-negative value,
8527      otherwise the result is implementation defined ", MY definition
8528      is that the sign does not get propagated */
8529
8530   right = IC_RIGHT (ic);
8531   left = IC_LEFT (ic);
8532   result = IC_RESULT (ic);
8533
8534   aopOp (right, ic, FALSE, FALSE);
8535
8536 #ifdef BETTER_LITERAL_SHIFT
8537   /* if the shift count is known then do it
8538      as efficiently as possible */
8539   if (AOP_TYPE (right) == AOP_LIT)
8540     {
8541       if (genRightShiftLiteral (left, right, result, ic, 0))
8542       {
8543         return;
8544       }
8545     }
8546 #endif
8547
8548   /* shift count is unknown then we have to form
8549      a loop get the loop count in B : Note: we take
8550      only the lower order byte since shifting
8551      more that 32 bits make no sense anyway, ( the
8552      largest size of an object can be only 32 bits ) */
8553   
8554   if (AOP_TYPE (right) == AOP_LIT)
8555   {
8556       /* Really should be handled by genRightShiftLiteral,
8557        * but since I'm too lazy to fix that today, at least we can make
8558        * some small improvement.
8559        */
8560        emitcode("mov", "b,#!constbyte",
8561                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8562   }
8563   else
8564   {
8565         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8566         emitcode ("inc", "b");
8567   }
8568   freeAsmop (right, NULL, ic, TRUE);
8569   aopOp (left, ic, FALSE, FALSE);
8570   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8571
8572   /* now move the left to the result if they are not the
8573      same */
8574   if (!sameRegs (AOP (left), AOP (result)) &&
8575       AOP_SIZE (result) > 1)
8576     {
8577
8578       size = AOP_SIZE (result);
8579       offset = 0;
8580       _startLazyDPSEvaluation ();
8581       while (size--)
8582         {
8583           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8584           if (*l == '@' && IS_AOP_PREG (result))
8585             {
8586
8587               emitcode ("mov", "a,%s", l);
8588               aopPut (AOP (result), "a", offset);
8589             }
8590           else
8591             aopPut (AOP (result), l, offset);
8592           offset++;
8593         }
8594       _endLazyDPSEvaluation ();
8595     }
8596
8597   tlbl = newiTempLabel (NULL);
8598   tlbl1 = newiTempLabel (NULL);
8599   size = AOP_SIZE (result);
8600   offset = size - 1;
8601
8602   /* if it is only one byte then */
8603   if (size == 1)
8604     {
8605       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8606       MOVA (l);
8607       emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8608       emitcode ("", "!tlabeldef", tlbl->key + 100);
8609       CLRC;
8610       emitcode ("rrc", "a");
8611       emitcode ("", "!tlabeldef", tlbl1->key + 100);
8612       emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8613       aopPut (AOP (result), "a", 0);
8614       goto release;
8615     }
8616
8617   reAdjustPreg (AOP (result));
8618   emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8619   emitcode ("", "!tlabeldef", tlbl->key + 100);
8620   CLRC;
8621   _startLazyDPSEvaluation ();
8622   while (size--)
8623     {
8624       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8625       MOVA (l);
8626       emitcode ("rrc", "a");
8627       aopPut (AOP (result), "a", offset--);
8628     }
8629   _endLazyDPSEvaluation ();
8630   reAdjustPreg (AOP (result));
8631
8632   emitcode ("", "!tlabeldef", tlbl1->key + 100);
8633   emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8634
8635 release:
8636   freeAsmop (left, NULL, ic, TRUE);
8637   freeAsmop (result, NULL, ic, TRUE);
8638 }
8639
8640 /*-----------------------------------------------------------------*/
8641 /* genUnpackBits - generates code for unpacking bits               */
8642 /*-----------------------------------------------------------------*/
8643 static void
8644 genUnpackBits (operand * result, char *rname, int ptype)
8645 {
8646   int shCnt;
8647   int rlen = 0;
8648   sym_link *etype;
8649   int offset = 0;
8650
8651   D (emitcode (";", "genUnpackBits ");
8652     );
8653
8654   etype = getSpec (operandType (result));
8655
8656   /* read the first byte  */
8657   switch (ptype)
8658     {
8659
8660     case POINTER:
8661     case IPOINTER:
8662       emitcode ("mov", "a,@%s", rname);
8663       break;
8664
8665     case PPOINTER:
8666       emitcode ("movx", "a,@%s", rname);
8667       break;
8668
8669     case FPOINTER:
8670       emitcode ("movx", "a,@dptr");
8671       break;
8672
8673     case CPOINTER:
8674       emitcode ("clr", "a");
8675       emitcode ("movc", "a,@a+dptr");
8676       break;
8677
8678     case GPOINTER:
8679       emitcode ("lcall", "__gptrget");
8680       break;
8681     }
8682
8683   /* if we have bitdisplacement then it fits   */
8684   /* into this byte completely or if length is */
8685   /* less than a byte                          */
8686   if ((shCnt = SPEC_BSTR (etype)) ||
8687       (SPEC_BLEN (etype) <= 8))
8688     {
8689
8690       /* shift right acc */
8691       AccRsh (shCnt);
8692
8693       emitcode ("anl", "a,#!constbyte",
8694                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8695       aopPut (AOP (result), "a", offset);
8696       return;
8697     }
8698
8699   /* bit field did not fit in a byte  */
8700   rlen = SPEC_BLEN (etype) - 8;
8701   aopPut (AOP (result), "a", offset++);
8702
8703   while (1)
8704     {
8705
8706       switch (ptype)
8707         {
8708         case POINTER:
8709         case IPOINTER:
8710           emitcode ("inc", "%s", rname);
8711           emitcode ("mov", "a,@%s", rname);
8712           break;
8713
8714         case PPOINTER:
8715           emitcode ("inc", "%s", rname);
8716           emitcode ("movx", "a,@%s", rname);
8717           break;
8718
8719         case FPOINTER:
8720           emitcode ("inc", "dptr");
8721           emitcode ("movx", "a,@dptr");
8722           break;
8723
8724         case CPOINTER:
8725           emitcode ("clr", "a");
8726           emitcode ("inc", "dptr");
8727           emitcode ("movc", "a,@a+dptr");
8728           break;
8729
8730         case GPOINTER:
8731           emitcode ("inc", "dptr");
8732           emitcode ("lcall", "__gptrget");
8733           break;
8734         }
8735
8736       rlen -= 8;
8737       /* if we are done */
8738       if (rlen < 8)
8739         break;
8740
8741       aopPut (AOP (result), "a", offset++);
8742
8743     }
8744
8745   if (rlen)
8746     {
8747       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
8748       aopPut (AOP (result), "a", offset);
8749     }
8750
8751   return;
8752 }
8753
8754
8755 /*-----------------------------------------------------------------*/
8756 /* genDataPointerGet - generates code when ptr offset is known     */
8757 /*-----------------------------------------------------------------*/
8758 static void
8759 genDataPointerGet (operand * left,
8760                    operand * result,
8761                    iCode * ic)
8762 {
8763   char *l;
8764   char buffer[256];
8765   int size, offset = 0;
8766   aopOp (result, ic, TRUE, FALSE);
8767
8768   /* get the string representation of the name */
8769   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8770   size = AOP_SIZE (result);
8771   _startLazyDPSEvaluation ();
8772   while (size--)
8773     {
8774       if (offset)
8775         sprintf (buffer, "(%s + %d)", l + 1, offset);
8776       else
8777         sprintf (buffer, "%s", l + 1);
8778       aopPut (AOP (result), buffer, offset++);
8779     }
8780   _endLazyDPSEvaluation ();
8781
8782   freeAsmop (left, NULL, ic, TRUE);
8783   freeAsmop (result, NULL, ic, TRUE);
8784 }
8785
8786 /*-----------------------------------------------------------------*/
8787 /* genNearPointerGet - emitcode for near pointer fetch             */
8788 /*-----------------------------------------------------------------*/
8789 static void
8790 genNearPointerGet (operand * left,
8791                    operand * result,
8792                    iCode * ic,
8793                    iCode *pi)
8794 {
8795   asmop *aop = NULL;
8796   regs *preg = NULL;
8797   char *rname;
8798   sym_link *rtype, *retype, *letype;
8799   sym_link *ltype = operandType (left);
8800   char buffer[80];
8801
8802   rtype = operandType (result);
8803   retype = getSpec (rtype);
8804   letype = getSpec (ltype);
8805
8806   aopOp (left, ic, FALSE, FALSE);
8807
8808   /* if left is rematerialisable and
8809      result is not bit variable type and
8810      the left is pointer to data space i.e
8811      lower 128 bytes of space */
8812   if (AOP_TYPE (left) == AOP_IMMD &&
8813       !IS_BITVAR (retype) &&
8814       !IS_BITVAR (letype) &&
8815       DCL_TYPE (ltype) == POINTER)
8816     {
8817       genDataPointerGet (left, result, ic);
8818       return;
8819     }
8820
8821   /* if the value is already in a pointer register
8822      then don't need anything more */
8823   if (!AOP_INPREG (AOP (left)))
8824     {
8825       /* otherwise get a free pointer register */
8826       aop = newAsmop (0);
8827       preg = getFreePtr (ic, &aop, FALSE);
8828       emitcode ("mov", "%s,%s",
8829                 preg->name,
8830                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8831       rname = preg->name;
8832     }
8833   else
8834     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8835
8836   freeAsmop (left, NULL, ic, TRUE);
8837   aopOp (result, ic, FALSE, FALSE);
8838
8839   /* if bitfield then unpack the bits */
8840   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8841     genUnpackBits (result, rname, POINTER);
8842   else
8843     {
8844       /* we have can just get the values */
8845       int size = AOP_SIZE (result);
8846       int offset = 0;
8847
8848       while (size--)
8849         {
8850           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8851             {
8852
8853               emitcode ("mov", "a,@%s", rname);
8854               aopPut (AOP (result), "a", offset);
8855             }
8856           else
8857             {
8858               sprintf (buffer, "@%s", rname);
8859               aopPut (AOP (result), buffer, offset);
8860             }
8861           offset++;
8862           if (size || pi)
8863             emitcode ("inc", "%s", rname);
8864         }
8865     }
8866
8867   /* now some housekeeping stuff */
8868   if (aop)
8869     {
8870       /* we had to allocate for this iCode */
8871       if (pi) { /* post increment present */
8872         aopPut(AOP ( left ),rname,0);
8873       }
8874       freeAsmop (NULL, aop, ic, TRUE);
8875     }
8876   else
8877     {
8878       /* we did not allocate which means left
8879          already in a pointer register, then
8880          if size > 0 && this could be used again
8881          we have to point it back to where it
8882          belongs */
8883       if (AOP_SIZE (result) > 1 &&
8884           !OP_SYMBOL (left)->remat &&
8885           (OP_SYMBOL (left)->liveTo > ic->seq ||
8886            ic->depth) &&
8887           !pi)
8888         {
8889           int size = AOP_SIZE (result) - 1;
8890           while (size--)
8891             emitcode ("dec", "%s", rname);
8892         }
8893     }
8894
8895   /* done */
8896   freeAsmop (result, NULL, ic, TRUE);
8897   if (pi) pi->generated = 1;
8898 }
8899
8900 /*-----------------------------------------------------------------*/
8901 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8902 /*-----------------------------------------------------------------*/
8903 static void
8904 genPagedPointerGet (operand * left,
8905                     operand * result,
8906                     iCode * ic,
8907                     iCode * pi)
8908 {
8909   asmop *aop = NULL;
8910   regs *preg = NULL;
8911   char *rname;
8912   sym_link *rtype, *retype, *letype;
8913
8914   rtype = operandType (result);
8915   retype = getSpec (rtype);
8916   letype = getSpec (operandType (left));
8917   aopOp (left, ic, FALSE, FALSE);
8918
8919   /* if the value is already in a pointer register
8920      then don't need anything more */
8921   if (!AOP_INPREG (AOP (left)))
8922     {
8923       /* otherwise get a free pointer register */
8924       aop = newAsmop (0);
8925       preg = getFreePtr (ic, &aop, FALSE);
8926       emitcode ("mov", "%s,%s",
8927                 preg->name,
8928                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8929       rname = preg->name;
8930     }
8931   else
8932     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8933
8934   freeAsmop (left, NULL, ic, TRUE);
8935   aopOp (result, ic, FALSE, FALSE);
8936
8937   /* if bitfield then unpack the bits */
8938   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8939     genUnpackBits (result, rname, PPOINTER);
8940   else
8941     {
8942       /* we have can just get the values */
8943       int size = AOP_SIZE (result);
8944       int offset = 0;
8945
8946       while (size--)
8947         {
8948
8949           emitcode ("movx", "a,@%s", rname);
8950           aopPut (AOP (result), "a", offset);
8951
8952           offset++;
8953
8954           if (size || pi)
8955             emitcode ("inc", "%s", rname);
8956         }
8957     }
8958
8959   /* now some housekeeping stuff */
8960   if (aop)
8961     {
8962       /* we had to allocate for this iCode */
8963       if (pi) aopPut ( AOP (left), rname, 0);
8964       freeAsmop (NULL, aop, ic, TRUE);
8965     }
8966   else
8967     {
8968       /* we did not allocate which means left
8969          already in a pointer register, then
8970          if size > 0 && this could be used again
8971          we have to point it back to where it
8972          belongs */
8973       if (AOP_SIZE (result) > 1 &&
8974           !OP_SYMBOL (left)->remat &&
8975           (OP_SYMBOL (left)->liveTo > ic->seq ||
8976            ic->depth) &&
8977           !pi)
8978         {
8979           int size = AOP_SIZE (result) - 1;
8980           while (size--)
8981             emitcode ("dec", "%s", rname);
8982         }
8983     }
8984
8985   /* done */
8986   freeAsmop (result, NULL, ic, TRUE);
8987   if (pi) pi->generated = 1;
8988 }
8989
8990 /*-----------------------------------------------------------------*/
8991 /* genFarPointerGet - gget value from far space                    */
8992 /*-----------------------------------------------------------------*/
8993 static void
8994 genFarPointerGet (operand * left,
8995                   operand * result, iCode * ic, iCode *pi)
8996 {
8997     int size, offset, dopi=1;
8998   sym_link *retype = getSpec (operandType (result));
8999   sym_link *letype = getSpec (operandType (left));
9000   D (emitcode (";", "genFarPointerGet");
9001     );
9002
9003   aopOp (left, ic, FALSE, FALSE);
9004
9005   /* if the operand is already in dptr
9006      then we do nothing else we move the value to dptr */
9007   if (AOP_TYPE (left) != AOP_STR)
9008     {
9009       /* if this is remateriazable */
9010       if (AOP_TYPE (left) == AOP_IMMD)
9011         {
9012           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9013         }
9014       else
9015         {
9016           /* we need to get it byte by byte */
9017           _startLazyDPSEvaluation ();
9018           if (AOP_TYPE (left) != AOP_DPTR)
9019             {
9020               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9021               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9022               if (options.model == MODEL_FLAT24)
9023                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9024             }
9025           else
9026             {
9027               /* We need to generate a load to DPTR indirect through DPTR. */
9028               D (emitcode (";", "genFarPointerGet -- indirection special case.");
9029                 );
9030               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9031               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9032               if (options.model == MODEL_FLAT24)
9033                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9034               emitcode ("pop", "dph");
9035               emitcode ("pop", "dpl");
9036               dopi =0;
9037             }
9038           _endLazyDPSEvaluation ();
9039         }
9040     }
9041   /* so dptr know contains the address */
9042   aopOp (result, ic, FALSE, TRUE);
9043
9044   /* if bit then unpack */
9045   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9046     genUnpackBits (result, "dptr", FPOINTER);
9047   else
9048     {
9049       size = AOP_SIZE (result);
9050       offset = 0;
9051
9052       _startLazyDPSEvaluation ();
9053       while (size--)
9054         {
9055
9056           genSetDPTR (0);
9057           _flushLazyDPS ();
9058
9059           emitcode ("movx", "a,@dptr");
9060           if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9061             emitcode ("inc", "dptr");
9062
9063           aopPut (AOP (result), "a", offset++);
9064         }
9065       _endLazyDPSEvaluation ();
9066     }
9067   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9068     aopPut ( AOP (left), "dpl", 0);
9069     aopPut ( AOP (left), "dph", 1);
9070     if (options.model == MODEL_FLAT24)
9071             aopPut ( AOP (left), "dpx", 2);
9072     pi->generated = 1;
9073   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9074              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9075       
9076       size = AOP_SIZE (result) - 1;
9077       while (size--) emitcode ("lcall","__decdptr");
9078   }
9079
9080   freeAsmop (left, NULL, ic, TRUE);
9081   freeAsmop (result, NULL, ic, TRUE);
9082 }
9083
9084 /*-----------------------------------------------------------------*/
9085 /* emitcodePointerGet - gget value from code space                  */
9086 /*-----------------------------------------------------------------*/
9087 static void
9088 emitcodePointerGet (operand * left,
9089                     operand * result, iCode * ic, iCode *pi)
9090 {
9091   int size, offset, dopi=1;
9092   sym_link *retype = getSpec (operandType (result));
9093
9094   aopOp (left, ic, FALSE, FALSE);
9095
9096   /* if the operand is already in dptr
9097      then we do nothing else we move the value to dptr */
9098   if (AOP_TYPE (left) != AOP_STR)
9099     {
9100       /* if this is remateriazable */
9101       if (AOP_TYPE (left) == AOP_IMMD)
9102         {
9103           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9104         }
9105       else
9106         {                       /* we need to get it byte by byte */
9107           _startLazyDPSEvaluation ();
9108           if (AOP_TYPE (left) != AOP_DPTR)
9109             {
9110               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9111               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9112               if (options.model == MODEL_FLAT24)
9113                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9114             }
9115           else
9116             {
9117               /* We need to generate a load to DPTR indirect through DPTR. */
9118               D (emitcode (";", "gencodePointerGet -- indirection special case.");
9119                 );
9120               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
9121               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
9122               if (options.model == MODEL_FLAT24)
9123                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9124               emitcode ("pop", "dph");
9125               emitcode ("pop", "dpl");
9126               dopi=0;
9127             }
9128           _endLazyDPSEvaluation ();
9129         }
9130     }
9131   /* so dptr know contains the address */
9132   aopOp (result, ic, FALSE, TRUE);
9133
9134   /* if bit then unpack */
9135   if (IS_BITVAR (retype))
9136     genUnpackBits (result, "dptr", CPOINTER);
9137   else
9138     {
9139       size = AOP_SIZE (result);
9140       offset = 0;
9141
9142       _startLazyDPSEvaluation ();
9143       while (size--)
9144         {
9145           genSetDPTR (0);
9146           _flushLazyDPS ();
9147
9148           emitcode ("clr", "a");
9149           emitcode ("movc", "a,@a+dptr");
9150           if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9151             emitcode ("inc", "dptr");
9152           aopPut (AOP (result), "a", offset++);
9153         }
9154       _endLazyDPSEvaluation ();
9155     }
9156   if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9157       aopPut ( AOP (left), "dpl", 0);
9158       aopPut ( AOP (left), "dph", 1);
9159       if (options.model == MODEL_FLAT24)
9160           aopPut ( AOP (left), "dpx", 2);
9161       pi->generated = 1;
9162   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9163              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9164       
9165       size = AOP_SIZE (result) - 1;
9166       while (size--) emitcode ("lcall","__decdptr");
9167   }
9168   
9169   freeAsmop (left, NULL, ic, TRUE);
9170   freeAsmop (result, NULL, ic, TRUE);
9171 }
9172
9173 /*-----------------------------------------------------------------*/
9174 /* genGenPointerGet - gget value from generic pointer space        */
9175 /*-----------------------------------------------------------------*/
9176 static void
9177 genGenPointerGet (operand * left,
9178                   operand * result, iCode * ic, iCode * pi)
9179 {
9180   int size, offset;
9181   sym_link *retype = getSpec (operandType (result));
9182   sym_link *letype = getSpec (operandType (left));
9183
9184   D (emitcode (";", "genGenPointerGet "); );
9185
9186   aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE));
9187
9188   /* if the operand is already in dptr
9189      then we do nothing else we move the value to dptr */
9190   if (AOP_TYPE (left) != AOP_STR)
9191     {
9192       /* if this is remateriazable */
9193       if (AOP_TYPE (left) == AOP_IMMD)
9194         {
9195           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
9196           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
9197                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE));
9198           else
9199                   emitcode ("mov", "b,#%d", pointerCode (retype));
9200         }
9201       else
9202         {                       /* we need to get it byte by byte */
9203           _startLazyDPSEvaluation ();
9204           if (AOP(left)->type==AOP_DPTR2) {
9205             char *l;
9206             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
9207             genSetDPTR(0);
9208             _flushLazyDPS();
9209             emitcode ("mov", "dpl,%s", l);
9210             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
9211             genSetDPTR(0);
9212             _flushLazyDPS();
9213             emitcode ("mov", "dph,%s", l);
9214             if (options.model == MODEL_FLAT24) {
9215               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
9216               genSetDPTR(0);
9217               _flushLazyDPS();
9218               emitcode ("mov", "dpx,%s", l);
9219               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9220             } else {
9221               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9222             }
9223           } else {
9224             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
9225             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
9226             if (options.model == MODEL_FLAT24) {
9227               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9228               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
9229             } else {
9230               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
9231             }
9232           }
9233           _endLazyDPSEvaluation ();
9234         }
9235     }
9236   /* so dptr know contains the address */
9237   aopOp (result, ic, FALSE, TRUE);
9238
9239   /* if bit then unpack */
9240   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9241     genUnpackBits (result, "dptr", GPOINTER);
9242   else
9243     {
9244       size = AOP_SIZE (result);
9245       offset = 0;
9246
9247       while (size--)
9248         {
9249           emitcode ("lcall", "__gptrget");
9250           aopPut (AOP (result), "a", offset++);
9251           if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9252             emitcode ("inc", "dptr");
9253         }
9254     }
9255
9256   if (pi && AOP_TYPE (left) != AOP_IMMD) {
9257     aopPut ( AOP (left), "dpl", 0);
9258     aopPut ( AOP (left), "dph", 1);
9259     if (options.model == MODEL_FLAT24) {
9260         aopPut ( AOP (left), "dpx", 2);
9261         aopPut ( AOP (left), "b", 3);   
9262     } else  aopPut ( AOP (left), "b", 2);       
9263     pi->generated = 1;
9264   } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9265              (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9266       
9267       size = AOP_SIZE (result) - 1;
9268       while (size--) emitcode ("lcall","__decdptr");
9269   }
9270
9271   freeAsmop (left, NULL, ic, TRUE);
9272   freeAsmop (result, NULL, ic, TRUE);
9273 }
9274
9275 /*-----------------------------------------------------------------*/
9276 /* genPointerGet - generate code for pointer get                   */
9277 /*-----------------------------------------------------------------*/
9278 static void
9279 genPointerGet (iCode * ic, iCode *pi)
9280 {
9281   operand *left, *result;
9282   sym_link *type, *etype;
9283   int p_type;
9284
9285   D (emitcode (";", "genPointerGet ");
9286     );
9287
9288   left = IC_LEFT (ic);
9289   result = IC_RESULT (ic);
9290
9291   /* depending on the type of pointer we need to
9292      move it to the correct pointer register */
9293   type = operandType (left);
9294   etype = getSpec (type);
9295   /* if left is of type of pointer then it is simple */
9296   if (IS_PTR (type) && !IS_FUNC (type->next))
9297     p_type = DCL_TYPE (type);
9298   else
9299     {
9300       /* we have to go by the storage class */
9301       p_type = PTR_TYPE (SPEC_OCLS (etype));
9302     }
9303   /* special case when cast remat */
9304   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9305       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9306           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9307           type =   type = operandType (left);
9308           p_type = DCL_TYPE (type);
9309   }
9310   /* now that we have the pointer type we assign
9311      the pointer values */
9312   switch (p_type)
9313     {
9314
9315     case POINTER:
9316     case IPOINTER:
9317       genNearPointerGet (left, result, ic, pi);
9318       break;
9319
9320     case PPOINTER:
9321       genPagedPointerGet (left, result, ic, pi);
9322       break;
9323
9324     case FPOINTER:
9325       genFarPointerGet (left, result, ic, pi);
9326       break;
9327
9328     case CPOINTER:
9329       emitcodePointerGet (left, result, ic, pi);
9330       break;
9331
9332     case GPOINTER:
9333       genGenPointerGet (left, result, ic, pi);
9334       break;
9335     }
9336
9337 }
9338
9339 /*-----------------------------------------------------------------*/
9340 /* genPackBits - generates code for packed bit storage             */
9341 /*-----------------------------------------------------------------*/
9342 static void
9343 genPackBits (sym_link * etype,
9344              operand * right,
9345              char *rname, int p_type)
9346 {
9347   int shCount = 0;
9348   int offset = 0;
9349   int rLen = 0;
9350   int blen, bstr;
9351   char *l;
9352
9353   blen = SPEC_BLEN (etype);
9354   bstr = SPEC_BSTR (etype);
9355
9356   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9357   MOVA (l);
9358
9359   /* if the bit lenth is less than or    */
9360   /* it exactly fits a byte then         */
9361   if (SPEC_BLEN (etype) <= 8)
9362     {
9363       shCount = SPEC_BSTR (etype);
9364
9365       /* shift left acc */
9366       AccLsh (shCount);
9367
9368       if (SPEC_BLEN (etype) < 8)
9369         {                       /* if smaller than a byte */
9370
9371
9372           switch (p_type)
9373             {
9374             case POINTER:
9375               emitcode ("mov", "b,a");
9376               emitcode ("mov", "a,@%s", rname);
9377               break;
9378
9379             case FPOINTER:
9380               emitcode ("mov", "b,a");
9381               emitcode ("movx", "a,@dptr");
9382               break;
9383
9384             case GPOINTER:
9385               emitcode ("push", "b");
9386               emitcode ("push", "acc");
9387               emitcode ("lcall", "__gptrget");
9388               emitcode ("pop", "b");
9389               break;
9390             }
9391
9392           emitcode ("anl", "a,#!constbyte", (unsigned char)
9393                     ((unsigned char) (0xFF << (blen + bstr)) |
9394                      (unsigned char) (0xFF >> (8 - bstr))));
9395           emitcode ("orl", "a,b");
9396           if (p_type == GPOINTER)
9397             emitcode ("pop", "b");
9398         }
9399     }
9400
9401   switch (p_type)
9402     {
9403     case POINTER:
9404       emitcode ("mov", "@%s,a", rname);
9405       break;
9406
9407     case FPOINTER:
9408       emitcode ("movx", "@dptr,a");
9409       break;
9410
9411     case GPOINTER:
9412       emitcode ("lcall", "__gptrput");
9413       break;
9414     }
9415
9416   /* if we r done */
9417   if (SPEC_BLEN (etype) <= 8)
9418     return;
9419
9420   emitcode ("inc", "%s", rname);
9421   rLen = SPEC_BLEN (etype);
9422
9423   /* now generate for lengths greater than one byte */
9424   while (1)
9425     {
9426
9427       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9428
9429       rLen -= 8;
9430       if (rLen < 8)
9431         break;
9432
9433       switch (p_type)
9434         {
9435         case POINTER:
9436           if (*l == '@')
9437             {
9438               MOVA (l);
9439               emitcode ("mov", "@%s,a", rname);
9440             }
9441           else
9442             emitcode ("mov", "@%s,%s", rname, l);
9443           break;
9444
9445         case FPOINTER:
9446           MOVA (l);
9447           emitcode ("movx", "@dptr,a");
9448           break;
9449
9450         case GPOINTER:
9451           MOVA (l);
9452           emitcode ("lcall", "__gptrput");
9453           break;
9454         }
9455       emitcode ("inc", "%s", rname);
9456     }
9457
9458   MOVA (l);
9459
9460   /* last last was not complete */
9461   if (rLen)
9462     {
9463       /* save the byte & read byte */
9464       switch (p_type)
9465         {
9466         case POINTER:
9467           emitcode ("mov", "b,a");
9468           emitcode ("mov", "a,@%s", rname);
9469           break;
9470
9471         case FPOINTER:
9472           emitcode ("mov", "b,a");
9473           emitcode ("movx", "a,@dptr");
9474           break;
9475
9476         case GPOINTER:
9477           emitcode ("push", "b");
9478           emitcode ("push", "acc");
9479           emitcode ("lcall", "__gptrget");
9480           emitcode ("pop", "b");
9481           break;
9482         }
9483
9484       emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
9485       emitcode ("orl", "a,b");
9486     }
9487
9488   if (p_type == GPOINTER)
9489     emitcode ("pop", "b");
9490
9491   switch (p_type)
9492     {
9493
9494     case POINTER:
9495       emitcode ("mov", "@%s,a", rname);
9496       break;
9497
9498     case FPOINTER:
9499       emitcode ("movx", "@dptr,a");
9500       break;
9501
9502     case GPOINTER:
9503       emitcode ("lcall", "__gptrput");
9504       break;
9505     }
9506 }
9507 /*-----------------------------------------------------------------*/
9508 /* genDataPointerSet - remat pointer to data space                 */
9509 /*-----------------------------------------------------------------*/
9510 static void
9511 genDataPointerSet (operand * right,
9512                    operand * result,
9513                    iCode * ic)
9514 {
9515   int size, offset = 0;
9516   char *l, buffer[256];
9517
9518   aopOp (right, ic, FALSE, FALSE);
9519
9520   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9521   size = AOP_SIZE (right);
9522   while (size--)
9523     {
9524       if (offset)
9525         sprintf (buffer, "(%s + %d)", l + 1, offset);
9526       else
9527         sprintf (buffer, "%s", l + 1);
9528       emitcode ("mov", "%s,%s", buffer,
9529                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9530     }
9531
9532   freeAsmop (right, NULL, ic, TRUE);
9533   freeAsmop (result, NULL, ic, TRUE);
9534 }
9535
9536 /*-----------------------------------------------------------------*/
9537 /* genNearPointerSet - emitcode for near pointer put                */
9538 /*-----------------------------------------------------------------*/
9539 static void
9540 genNearPointerSet (operand * right,
9541                    operand * result,
9542                    iCode * ic,
9543                    iCode * pi)
9544 {
9545   asmop *aop = NULL;
9546   regs *preg = NULL;
9547   char *rname, *l;
9548   sym_link *retype, *letype;
9549   sym_link *ptype = operandType (result);
9550
9551   retype = getSpec (operandType (right));
9552   letype = getSpec (ptype);
9553
9554   aopOp (result, ic, FALSE, FALSE);
9555
9556   /* if the result is rematerializable &
9557      in data space & not a bit variable */
9558   if (AOP_TYPE (result) == AOP_IMMD &&
9559       DCL_TYPE (ptype) == POINTER &&
9560       !IS_BITVAR (retype) &&
9561       !IS_BITVAR (letype))
9562     {
9563       genDataPointerSet (right, result, ic);
9564       return;
9565     }
9566
9567   /* if the value is already in a pointer register
9568      then don't need anything more */
9569   if (!AOP_INPREG (AOP (result)))
9570     {
9571       /* otherwise get a free pointer register */
9572       aop = newAsmop (0);
9573       preg = getFreePtr (ic, &aop, FALSE);
9574       emitcode ("mov", "%s,%s",
9575                 preg->name,
9576                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9577       rname = preg->name;
9578     }
9579   else
9580     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9581
9582   aopOp (right, ic, FALSE, FALSE);
9583
9584   /* if bitfield then unpack the bits */
9585   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9586     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9587   else
9588     {
9589       /* we have can just get the values */
9590       int size = AOP_SIZE (right);
9591       int offset = 0;
9592
9593       while (size--)
9594         {
9595           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9596           if (*l == '@')
9597             {
9598               MOVA (l);
9599               emitcode ("mov", "@%s,a", rname);
9600             }
9601           else
9602             emitcode ("mov", "@%s,%s", rname, l);
9603           if (size || pi)
9604             emitcode ("inc", "%s", rname);
9605           offset++;
9606         }
9607     }
9608
9609   /* now some housekeeping stuff */
9610   if (aop)
9611     {
9612       /* we had to allocate for this iCode */
9613       if (pi) aopPut (AOP (result),rname,0);
9614       freeAsmop (NULL, aop, ic, TRUE);
9615     }
9616   else
9617     {
9618       /* we did not allocate which means left
9619          already in a pointer register, then
9620          if size > 0 && this could be used again
9621          we have to point it back to where it
9622          belongs */
9623       if (AOP_SIZE (right) > 1 &&
9624           !OP_SYMBOL (result)->remat &&
9625           (OP_SYMBOL (result)->liveTo > ic->seq ||
9626            ic->depth) &&
9627           !pi)
9628         {
9629           int size = AOP_SIZE (right) - 1;
9630           while (size--)
9631             emitcode ("dec", "%s", rname);
9632         }
9633     }
9634
9635   /* done */
9636   if (pi) pi->generated = 1;
9637   freeAsmop (result, NULL, ic, TRUE);
9638   freeAsmop (right, NULL, ic, TRUE);
9639
9640
9641 }
9642
9643 /*-----------------------------------------------------------------*/
9644 /* genPagedPointerSet - emitcode for Paged pointer put             */
9645 /*-----------------------------------------------------------------*/
9646 static void
9647 genPagedPointerSet (operand * right,
9648                     operand * result,
9649                     iCode * ic,
9650                     iCode *pi)
9651 {
9652   asmop *aop = NULL;
9653   regs *preg = NULL;
9654   char *rname, *l;
9655   sym_link *retype, *letype;
9656
9657   retype = getSpec (operandType (right));
9658   letype = getSpec (operandType (result));
9659
9660   aopOp (result, ic, FALSE, FALSE);
9661
9662   /* if the value is already in a pointer register
9663      then don't need anything more */
9664   if (!AOP_INPREG (AOP (result)))
9665     {
9666       /* otherwise get a free pointer register */
9667       aop = newAsmop (0);
9668       preg = getFreePtr (ic, &aop, FALSE);
9669       emitcode ("mov", "%s,%s",
9670                 preg->name,
9671                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9672       rname = preg->name;
9673     }
9674   else
9675     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9676
9677   aopOp (right, ic, FALSE, FALSE);
9678
9679   /* if bitfield then unpack the bits */
9680   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9681     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9682   else
9683     {
9684       /* we have can just get the values */
9685       int size = AOP_SIZE (right);
9686       int offset = 0;
9687
9688       while (size--)
9689         {
9690           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9691
9692           MOVA (l);
9693           emitcode ("movx", "@%s,a", rname);
9694
9695           if (size || pi)
9696             emitcode ("inc", "%s", rname);
9697
9698           offset++;
9699         }
9700     }
9701
9702   /* now some housekeeping stuff */
9703   if (aop)
9704     {
9705       if (pi) aopPut (AOP (result),rname,0);
9706       /* we had to allocate for this iCode */
9707       freeAsmop (NULL, aop, ic, TRUE);
9708     }
9709   else
9710     {
9711       /* we did not allocate which means left
9712          already in a pointer register, then
9713          if size > 0 && this could be used again
9714          we have to point it back to where it
9715          belongs */
9716       if (AOP_SIZE (right) > 1 &&
9717           !OP_SYMBOL (result)->remat &&
9718           (OP_SYMBOL (result)->liveTo > ic->seq ||
9719            ic->depth) &&
9720           !pi)
9721         {
9722           int size = AOP_SIZE (right) - 1;
9723           while (size--)
9724             emitcode ("dec", "%s", rname);
9725         }
9726     }
9727
9728   /* done */
9729   if (pi) pi->generated = 1;
9730   freeAsmop (result, NULL, ic, TRUE);
9731   freeAsmop (right, NULL, ic, TRUE);
9732
9733
9734 }
9735
9736 /*-----------------------------------------------------------------*/
9737 /* genFarPointerSet - set value from far space                     */
9738 /*-----------------------------------------------------------------*/
9739 static void
9740 genFarPointerSet (operand * right,
9741                   operand * result, iCode * ic, iCode *pi)
9742 {
9743   int size, offset, dopi=1;
9744   sym_link *retype = getSpec (operandType (right));
9745   sym_link *letype = getSpec (operandType (result));
9746
9747   aopOp (result, ic, FALSE, FALSE);
9748
9749   /* if the operand is already in dptr
9750      then we do nothing else we move the value to dptr */
9751   if (AOP_TYPE (result) != AOP_STR)
9752     {
9753       /* if this is remateriazable */
9754       if (AOP_TYPE (result) == AOP_IMMD)
9755         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9756       else
9757         {
9758           /* we need to get it byte by byte */
9759           _startLazyDPSEvaluation ();
9760           if (AOP_TYPE (result) != AOP_DPTR)
9761             {
9762               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9763               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9764               if (options.model == MODEL_FLAT24)
9765                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9766             }
9767           else
9768             {
9769               /* We need to generate a load to DPTR indirect through DPTR. */
9770               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9771                 );
9772               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9773               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9774               if (options.model == MODEL_FLAT24)
9775                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9776               emitcode ("pop", "dph");
9777               emitcode ("pop", "dpl");
9778               dopi=0;
9779             }
9780           _endLazyDPSEvaluation ();
9781         }
9782     }
9783   /* so dptr know contains the address */
9784   aopOp (right, ic, FALSE, TRUE);
9785
9786   /* if bit then unpack */
9787   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9788     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9789   else
9790     {
9791       size = AOP_SIZE (right);
9792       offset = 0;
9793
9794       _startLazyDPSEvaluation ();
9795       while (size--)
9796         {
9797           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9798           MOVA (l);
9799
9800           genSetDPTR (0);
9801           _flushLazyDPS ();
9802
9803           emitcode ("movx", "@dptr,a");
9804           if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
9805             emitcode ("inc", "dptr");
9806         }
9807       _endLazyDPSEvaluation ();
9808     }
9809
9810   if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
9811       aopPut (AOP(result),"dpl",0);
9812       aopPut (AOP(result),"dph",1);
9813       if (options.model == MODEL_FLAT24)
9814           aopPut (AOP(result),"dpx",2);
9815       pi->generated=1;
9816   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9817              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9818       
9819       size = AOP_SIZE (right) - 1;
9820       while (size--) emitcode ("lcall","__decdptr");
9821   }
9822   freeAsmop (result, NULL, ic, TRUE);
9823   freeAsmop (right, NULL, ic, TRUE);
9824 }
9825
9826 /*-----------------------------------------------------------------*/
9827 /* genGenPointerSet - set value from generic pointer space         */
9828 /*-----------------------------------------------------------------*/
9829 static void
9830 genGenPointerSet (operand * right,
9831                   operand * result, iCode * ic, iCode *pi)
9832 {
9833   int size, offset;
9834   sym_link *retype = getSpec (operandType (right));
9835   sym_link *letype = getSpec (operandType (result));
9836
9837   aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE);
9838
9839   /* if the operand is already in dptr
9840      then we do nothing else we move the value to dptr */
9841   if (AOP_TYPE (result) != AOP_STR)
9842     {
9843       _startLazyDPSEvaluation ();
9844       /* if this is remateriazable */
9845       if (AOP_TYPE (result) == AOP_IMMD)
9846         {
9847           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9848           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
9849                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE));
9850           else
9851                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9852         }
9853       else
9854         {                       /* we need to get it byte by byte */
9855           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9856           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9857           if (options.model == MODEL_FLAT24) {
9858             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9859             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9860           } else {
9861             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9862           }
9863         }
9864       _endLazyDPSEvaluation ();
9865     }
9866   /* so dptr know contains the address */
9867   aopOp (right, ic, FALSE, TRUE);
9868
9869   /* if bit then unpack */
9870   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9871     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9872   else
9873     {
9874       size = AOP_SIZE (right);
9875       offset = 0;
9876
9877       _startLazyDPSEvaluation ();
9878       while (size--)
9879         {
9880           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9881           MOVA (l);
9882
9883           genSetDPTR (0);
9884           _flushLazyDPS ();
9885
9886           emitcode ("lcall", "__gptrput");
9887           if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
9888             emitcode ("inc", "dptr");
9889         }
9890       _endLazyDPSEvaluation ();
9891     }
9892
9893   if (pi && AOP_TYPE (result) != AOP_IMMD) {
9894       aopPut (AOP(result),"dpl",0);
9895       aopPut (AOP(result),"dph",1);
9896       if (options.model == MODEL_FLAT24) {
9897           aopPut (AOP(result),"dpx",2);
9898           aopPut (AOP(result),"b",3);
9899       } else {
9900           aopPut (AOP(result),"b",2);
9901       }
9902       pi->generated=1;
9903   } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
9904              (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
9905       
9906       size = AOP_SIZE (right) - 1;
9907       while (size--) emitcode ("lcall","__decdptr");
9908   }
9909   freeAsmop (result, NULL, ic, TRUE);
9910   freeAsmop (right, NULL, ic, TRUE);
9911 }
9912
9913 /*-----------------------------------------------------------------*/
9914 /* genPointerSet - stores the value into a pointer location        */
9915 /*-----------------------------------------------------------------*/
9916 static void
9917 genPointerSet (iCode * ic, iCode *pi)
9918 {
9919   operand *right, *result;
9920   sym_link *type, *etype;
9921   int p_type;
9922
9923   D (emitcode (";", "genPointerSet ");
9924     );
9925
9926   right = IC_RIGHT (ic);
9927   result = IC_RESULT (ic);
9928
9929   /* depending on the type of pointer we need to
9930      move it to the correct pointer register */
9931   type = operandType (result);
9932   etype = getSpec (type);
9933   /* if left is of type of pointer then it is simple */
9934   if (IS_PTR (type) && !IS_FUNC (type->next))
9935     {
9936       p_type = DCL_TYPE (type);
9937     }
9938   else
9939     {
9940       /* we have to go by the storage class */
9941       p_type = PTR_TYPE (SPEC_OCLS (etype));
9942     }
9943   /* special case when cast remat */
9944   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9945       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9946           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9947           type =   type = operandType (result);
9948           p_type = DCL_TYPE (type);
9949   }
9950
9951   /* now that we have the pointer type we assign
9952      the pointer values */
9953   switch (p_type)
9954     {
9955
9956     case POINTER:
9957     case IPOINTER:
9958       genNearPointerSet (right, result, ic, pi);
9959       break;
9960
9961     case PPOINTER:
9962       genPagedPointerSet (right, result, ic, pi);
9963       break;
9964
9965     case FPOINTER:
9966       genFarPointerSet (right, result, ic, pi);
9967       break;
9968
9969     case GPOINTER:
9970       genGenPointerSet (right, result, ic, pi);
9971       break;
9972     }
9973
9974 }
9975
9976 /*-----------------------------------------------------------------*/
9977 /* genIfx - generate code for Ifx statement                        */
9978 /*-----------------------------------------------------------------*/
9979 static void
9980 genIfx (iCode * ic, iCode * popIc)
9981 {
9982   operand *cond = IC_COND (ic);
9983   int isbit = 0;
9984
9985   D (emitcode (";", "genIfx "););
9986
9987   aopOp (cond, ic, FALSE, FALSE);
9988
9989   /* get the value into acc */
9990   if (AOP_TYPE (cond) != AOP_CRY)
9991     toBoolean (cond);
9992   else
9993     isbit = 1;
9994   /* the result is now in the accumulator */
9995   freeAsmop (cond, NULL, ic, TRUE);
9996
9997   /* if there was something to be popped then do it */
9998   if (popIc)
9999     genIpop (popIc);
10000
10001   /* if the condition is  a bit variable */
10002   if (isbit && IS_ITEMP (cond) &&
10003       SPIL_LOC (cond))
10004     genIfxJump (ic, SPIL_LOC (cond)->rname);
10005   else if (isbit && !IS_ITEMP (cond))
10006     genIfxJump (ic, OP_SYMBOL (cond)->rname);
10007   else
10008     genIfxJump (ic, "a");
10009
10010   ic->generated = 1;
10011 }
10012
10013 /*-----------------------------------------------------------------*/
10014 /* genAddrOf - generates code for address of                       */
10015 /*-----------------------------------------------------------------*/
10016 static void
10017 genAddrOf (iCode * ic)
10018 {
10019   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10020   int size, offset;
10021
10022   D (emitcode (";", "genAddrOf ");
10023     );
10024
10025   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10026
10027   /* if the operand is on the stack then we
10028      need to get the stack offset of this
10029      variable */
10030   if (sym->onStack) {
10031       
10032       /* if 10 bit stack */
10033       if (options.stack10bit) {
10034           char buff[10];
10035           tsprintf(buff,"#!constbyte",(options.stack_loc >> 16) & 0xff);
10036           /* if it has an offset then we need to compute it */
10037           emitcode ("subb", "a,#!constbyte",
10038                     -((sym->stack < 0) ?
10039                       ((short) (sym->stack - _G.nRegsSaved)) :
10040                       ((short) sym->stack)) & 0xff);
10041           emitcode ("mov","b,a");
10042           emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ?
10043                                          ((short) (sym->stack - _G.nRegsSaved)) :
10044                                          ((short) sym->stack)) >> 8) & 0xff);
10045           if (sym->stack) {
10046               emitcode ("mov", "a,_bpx");
10047               emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ? 
10048                                              ((char) (sym->stack - _G.nRegsSaved)) :
10049                                              ((char) sym->stack )) & 0xff);
10050               emitcode ("mov", "b,a");
10051               emitcode ("mov", "a,_bpx+1");
10052               emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
10053                                               ((short) (sym->stack - _G.nRegsSaved)) :
10054                                               ((short) sym->stack )) >> 8) & 0xff);
10055               aopPut (AOP (IC_RESULT (ic)), "b", 0);
10056               aopPut (AOP (IC_RESULT (ic)), "a", 1);
10057               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10058           } else {
10059               /* we can just move _bp */
10060               aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10061               aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10062               aopPut (AOP (IC_RESULT (ic)), buff, 2);
10063           }       
10064       } else {
10065           /* if it has an offset then we need to compute it */
10066           if (sym->stack) {
10067               emitcode ("mov", "a,_bp");
10068               emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10069               aopPut (AOP (IC_RESULT (ic)), "a", 0);
10070           } else {
10071               /* we can just move _bp */
10072               aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10073           }
10074           /* fill the result with zero */
10075           size = AOP_SIZE (IC_RESULT (ic)) - 1;
10076           
10077           
10078           if (options.stack10bit && size < (FPTRSIZE - 1)) {
10079               fprintf (stderr,
10080                        "*** warning: pointer to stack var truncated.\n");
10081           }
10082
10083           offset = 1;
10084           while (size--) {
10085               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10086           }      
10087       }
10088       goto release;
10089   }
10090
10091   /* object not on stack then we need the name */
10092   size = AOP_SIZE (IC_RESULT (ic));
10093   offset = 0;
10094
10095   while (size--)
10096     {
10097       char s[SDCC_NAME_MAX];
10098       if (offset) {
10099           switch (offset) {
10100           case 1:
10101               tsprintf(s,"!his",sym->rname);
10102               break;
10103           case 2:
10104               tsprintf(s,"!hihis",sym->rname);
10105               break;
10106           case 3:
10107               tsprintf(s,"!hihihis",sym->rname);
10108               break;
10109           default: /* should not need this (just in case) */
10110               sprintf (s, "#(%s >> %d)",
10111                        sym->rname,
10112                        offset * 8);
10113           }
10114       } else
10115           sprintf (s, "#%s", sym->rname);
10116       aopPut (AOP (IC_RESULT (ic)), s, offset++);
10117     }
10118
10119 release:
10120   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10121
10122 }
10123
10124 /*-----------------------------------------------------------------*/
10125 /* genArrayInit - generates code for address of                       */
10126 /*-----------------------------------------------------------------*/
10127 static void
10128 genArrayInit (iCode * ic)
10129 {
10130     literalList *iLoop;
10131     int         ix, count;
10132     int         elementSize = 0, eIndex;
10133     unsigned    val, lastVal;
10134     sym_link    *type;
10135     operand     *left=IC_LEFT(ic);
10136     
10137     D (emitcode (";", "genArrayInit "););
10138
10139     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10140     
10141     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10142     {
10143         // Load immediate value into DPTR.
10144         emitcode("mov", "dptr, %s",
10145              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
10146     }
10147     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10148     {
10149 #if 0
10150       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10151               "Unexpected operand to genArrayInit.\n");
10152       exit(1);
10153 #else
10154       // a regression because of SDCCcse.c:1.52
10155       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
10156       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
10157       if (options.model == MODEL_FLAT24)
10158         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
10159 #endif
10160     }
10161     
10162     type = operandType(IC_LEFT(ic));
10163     
10164     if (type && type->next)
10165     {
10166         elementSize = getSize(type->next);
10167     }
10168     else
10169     {
10170         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10171                                 "can't determine element size in genArrayInit.\n");
10172         exit(1);
10173     }
10174     
10175     iLoop = IC_ARRAYILIST(ic);
10176     lastVal = 0xffff;
10177     
10178     while (iLoop)
10179     {
10180         bool firstpass = TRUE;
10181         
10182         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
10183                  iLoop->count, (int)iLoop->literalValue, elementSize);
10184         
10185         ix = iLoop->count;
10186         
10187         while (ix)
10188         {
10189             symbol *tlbl = NULL;
10190             
10191             count = ix > 256 ? 256 : ix;
10192             
10193             if (count > 1)
10194             {
10195                 tlbl = newiTempLabel (NULL);
10196                 if (firstpass || (count & 0xff))
10197                 {
10198                     emitcode("mov", "b, #!constbyte", count & 0xff);
10199                 }
10200                 
10201                 emitcode ("", "!tlabeldef", tlbl->key + 100);
10202             }
10203             
10204             firstpass = FALSE;
10205                 
10206             for (eIndex = 0; eIndex < elementSize; eIndex++)
10207             {
10208                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10209                 if (val != lastVal)
10210                 {
10211                     emitcode("mov", "a, #!constbyte", val);
10212                     lastVal = val;
10213                 }
10214                 
10215                 emitcode("movx", "@dptr, a");
10216                 emitcode("inc", "dptr");
10217             }
10218             
10219             if (count > 1)
10220             {
10221                 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10222             }
10223             
10224             ix -= count;
10225         }
10226         
10227         iLoop = iLoop->next;
10228     }
10229     
10230     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10231 }
10232
10233 /*-----------------------------------------------------------------*/
10234 /* genFarFarAssign - assignment when both are in far space         */
10235 /*-----------------------------------------------------------------*/
10236 static void
10237 genFarFarAssign (operand * result, operand * right, iCode * ic)
10238 {
10239   int size = AOP_SIZE (right);
10240   int offset = 0;
10241   symbol *rSym = NULL;
10242
10243   if (size == 1)
10244   {
10245       /* quick & easy case. */
10246       D(emitcode(";","genFarFarAssign (1 byte case)"););      
10247       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
10248       freeAsmop (right, NULL, ic, FALSE);
10249       /* now assign DPTR to result */
10250       _G.accInUse++;
10251       aopOp(result, ic, FALSE, FALSE);
10252       _G.accInUse--;
10253       aopPut(AOP(result), "a", 0);
10254       freeAsmop(result, NULL, ic, FALSE);
10255       return;
10256   }
10257   
10258   /* See if we've got an underlying symbol to abuse. */
10259   if (IS_SYMOP(result) && OP_SYMBOL(result))
10260   {
10261       if (IS_TRUE_SYMOP(result))
10262       {
10263           rSym = OP_SYMBOL(result);
10264       }
10265       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10266       {
10267           rSym = OP_SYMBOL(result)->usl.spillLoc;
10268       }
10269   }
10270              
10271   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10272   {
10273       /* We can use the '390 auto-toggle feature to good effect here. */
10274       
10275       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10276       emitcode("mov", "dps,#!constbyte",0x21);  /* Select DPTR2 & auto-toggle. */
10277       emitcode ("mov", "dptr,#%s", rSym->rname); 
10278       /* DP2 = result, DP1 = right, DP1 is current. */
10279       while (size)
10280       {
10281           emitcode("movx", "a,@dptr");
10282           emitcode("movx", "@dptr,a");
10283           if (--size)
10284           {
10285                emitcode("inc", "dptr");
10286                emitcode("inc", "dptr");
10287           }
10288       }
10289       emitcode("mov", "dps,#0");
10290       freeAsmop (right, NULL, ic, FALSE);
10291 #if 0
10292 some alternative code for processors without auto-toggle
10293 no time to test now, so later well put in...kpb
10294         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10295         emitcode("mov", "dps,#1");      /* Select DPTR2. */
10296         emitcode ("mov", "dptr,#%s", rSym->rname); 
10297         /* DP2 = result, DP1 = right, DP1 is current. */
10298         while (size)
10299         {
10300           --size;
10301           emitcode("movx", "a,@dptr");
10302           if (size)
10303             emitcode("inc", "dptr");
10304           emitcode("inc", "dps");
10305           emitcode("movx", "@dptr,a");
10306           if (size)
10307             emitcode("inc", "dptr");
10308           emitcode("inc", "dps");
10309         }
10310         emitcode("mov", "dps,#0");
10311         freeAsmop (right, NULL, ic, FALSE);
10312 #endif
10313   }
10314   else
10315   {
10316       D (emitcode (";", "genFarFarAssign"););
10317       aopOp (result, ic, TRUE, TRUE);
10318
10319       _startLazyDPSEvaluation ();
10320       
10321       while (size--)
10322         {
10323           aopPut (AOP (result),
10324                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
10325           offset++;
10326         }
10327       _endLazyDPSEvaluation ();
10328       freeAsmop (result, NULL, ic, FALSE);
10329       freeAsmop (right, NULL, ic, FALSE);
10330   }
10331 }
10332
10333 /*-----------------------------------------------------------------*/
10334 /* genAssign - generate code for assignment                        */
10335 /*-----------------------------------------------------------------*/
10336 static void
10337 genAssign (iCode * ic)
10338 {
10339   operand *result, *right;
10340   int size, offset;
10341   unsigned long lit = 0L;
10342
10343   D (emitcode (";", "genAssign ");
10344     );
10345
10346   result = IC_RESULT (ic);
10347   right = IC_RIGHT (ic);
10348
10349   /* if they are the same */
10350   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10351     return;
10352
10353   aopOp (right, ic, FALSE, FALSE);
10354
10355   emitcode (";", "genAssign: resultIsFar = %s",
10356             isOperandInFarSpace (result) ?
10357             "TRUE" : "FALSE");
10358
10359   /* special case both in far space */
10360   if ((AOP_TYPE (right) == AOP_DPTR ||
10361        AOP_TYPE (right) == AOP_DPTR2) &&
10362   /* IS_TRUE_SYMOP(result)       && */
10363       isOperandInFarSpace (result))
10364     {
10365       genFarFarAssign (result, right, ic);
10366       return;
10367     }
10368
10369   aopOp (result, ic, TRUE, FALSE);
10370
10371   /* if they are the same registers */
10372   if (sameRegs (AOP (right), AOP (result)))
10373     goto release;
10374
10375   /* if the result is a bit */
10376   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10377     {
10378       /* if the right size is a literal then
10379          we know what the value is */
10380       if (AOP_TYPE (right) == AOP_LIT)
10381         {
10382           if (((int) operandLitValue (right)))
10383             aopPut (AOP (result), one, 0);
10384           else
10385             aopPut (AOP (result), zero, 0);
10386           goto release;
10387         }
10388
10389       /* the right is also a bit variable */
10390       if (AOP_TYPE (right) == AOP_CRY)
10391         {
10392           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10393           aopPut (AOP (result), "c", 0);
10394           goto release;
10395         }
10396
10397       /* we need to or */
10398       toBoolean (right);
10399       aopPut (AOP (result), "a", 0);
10400       goto release;
10401     }
10402
10403   /* bit variables done */
10404   /* general case */
10405   size = AOP_SIZE (result);
10406   offset = 0;
10407   if (AOP_TYPE (right) == AOP_LIT)
10408     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10409
10410   if ((size > 1) &&
10411       (AOP_TYPE (result) != AOP_REG) &&
10412       (AOP_TYPE (right) == AOP_LIT) &&
10413       !IS_FLOAT (operandType (right)))
10414     {
10415       _startLazyDPSEvaluation ();
10416       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10417         {
10418           aopPut (AOP (result),
10419                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
10420                   offset);
10421           offset++;
10422           size--;
10423         }
10424       /* And now fill the rest with zeros. */
10425       if (size)
10426         {
10427           emitcode ("clr", "a");
10428         }
10429       while (size--)
10430         {
10431           aopPut (AOP (result), "a", offset++);
10432         }
10433       _endLazyDPSEvaluation ();
10434     }
10435   else
10436     {
10437       _startLazyDPSEvaluation ();
10438       while (size--)
10439         {
10440           aopPut (AOP (result),
10441                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10442                   offset);
10443           offset++;
10444         }
10445       _endLazyDPSEvaluation ();
10446     }
10447
10448 release:
10449   freeAsmop (right, NULL, ic, FALSE);
10450   freeAsmop (result, NULL, ic, TRUE);
10451 }
10452
10453 /*-----------------------------------------------------------------*/
10454 /* genJumpTab - generates code for jump table                      */
10455 /*-----------------------------------------------------------------*/
10456 static void
10457 genJumpTab (iCode * ic)
10458 {
10459   symbol *jtab;
10460   char *l;
10461
10462   D (emitcode (";", "genJumpTab ");
10463     );
10464
10465   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10466   /* get the condition into accumulator */
10467   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10468   MOVA (l);
10469   /* multiply by four! */
10470   emitcode ("add", "a,acc");
10471   emitcode ("add", "a,acc");
10472   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10473
10474   jtab = newiTempLabel (NULL);
10475   emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
10476   emitcode ("jmp", "@a+dptr");
10477   emitcode ("", "!tlabeldef", jtab->key + 100);
10478   /* now generate the jump labels */
10479   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10480        jtab = setNextItem (IC_JTLABELS (ic)))
10481     emitcode ("ljmp", "!tlabel", jtab->key + 100);
10482
10483 }
10484
10485 /*-----------------------------------------------------------------*/
10486 /* genCast - gen code for casting                                  */
10487 /*-----------------------------------------------------------------*/
10488 static void
10489 genCast (iCode * ic)
10490 {
10491   operand *result = IC_RESULT (ic);
10492   sym_link *ctype = operandType (IC_LEFT (ic));
10493   sym_link *rtype = operandType (IC_RIGHT (ic));
10494   operand *right = IC_RIGHT (ic);
10495   int size, offset;
10496
10497   D (emitcode (";", "genCast ");
10498     );
10499
10500   /* if they are equivalent then do nothing */
10501   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10502     return;
10503
10504   aopOp (right, ic, FALSE, FALSE);
10505   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10506
10507   /* if the result is a bit */
10508   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10509   if (IS_BITVAR(OP_SYMBOL(result)->type))
10510     {
10511       /* if the right size is a literal then
10512          we know what the value is */
10513       if (AOP_TYPE (right) == AOP_LIT)
10514         {
10515           if (((int) operandLitValue (right)))
10516             aopPut (AOP (result), one, 0);
10517           else
10518             aopPut (AOP (result), zero, 0);
10519
10520           goto release;
10521         }
10522
10523       /* the right is also a bit variable */
10524       if (AOP_TYPE (right) == AOP_CRY)
10525         {
10526           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10527           aopPut (AOP (result), "c", 0);
10528           goto release;
10529         }
10530
10531       /* we need to or */
10532       toBoolean (right);
10533       aopPut (AOP (result), "a", 0);
10534       goto release;
10535     }
10536
10537   /* if they are the same size : or less */
10538   if (AOP_SIZE (result) <= AOP_SIZE (right))
10539     {
10540
10541       /* if they are in the same place */
10542       if (sameRegs (AOP (right), AOP (result)))
10543         goto release;
10544
10545       /* if they in different places then copy */
10546       size = AOP_SIZE (result);
10547       offset = 0;
10548       _startLazyDPSEvaluation ();
10549       while (size--)
10550         {
10551           aopPut (AOP (result),
10552                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10553                   offset);
10554           offset++;
10555         }
10556       _endLazyDPSEvaluation ();
10557       goto release;
10558     }
10559
10560
10561   /* if the result is of type pointer */
10562   if (IS_PTR (ctype))
10563     {
10564
10565       int p_type;
10566       sym_link *type = operandType (right);
10567
10568       /* pointer to generic pointer */
10569       if (IS_GENPTR (ctype))
10570         {
10571           char *l = zero;
10572
10573           if (IS_PTR (type))
10574             {
10575               p_type = DCL_TYPE (type);
10576             }
10577           else
10578             {
10579 #if OLD_CAST_BEHAVIOR
10580               /* KV: we are converting a non-pointer type to
10581                * a generic pointer. This (ifdef'd out) code
10582                * says that the resulting generic pointer
10583                * should have the same class as the storage
10584                * location of the non-pointer variable.
10585                *
10586                * For example, converting an int (which happens
10587                * to be stored in DATA space) to a pointer results
10588                * in a DATA generic pointer; if the original int
10589                * in XDATA space, so will be the resulting pointer.
10590                *
10591                * I don't like that behavior, and thus this change:
10592                * all such conversions will be forced to XDATA and
10593                * throw a warning. If you want some non-XDATA
10594                * type, or you want to suppress the warning, you
10595                * must go through an intermediate cast, like so:
10596                *
10597                * char _generic *gp = (char _xdata *)(intVar);
10598                */
10599               sym_link *etype = getSpec (type);
10600
10601               /* we have to go by the storage class */
10602               if (SPEC_OCLS (etype) != generic)
10603                 {
10604                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10605                 }
10606               else
10607 #endif
10608                 {
10609                   /* Converting unknown class (i.e. register variable)
10610                    * to generic pointer. This is not good, but
10611                    * we'll make a guess (and throw a warning).
10612                    */
10613                   p_type = FPOINTER;
10614                   werror (W_INT_TO_GEN_PTR_CAST);
10615                 }
10616             }
10617
10618           /* the first two bytes are known */
10619           size = GPTRSIZE - 1;
10620           offset = 0;
10621           _startLazyDPSEvaluation ();
10622           while (size--)
10623             {
10624               aopPut (AOP (result),
10625                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10626                       offset);
10627               offset++;
10628             }
10629           _endLazyDPSEvaluation ();
10630
10631           /* the last byte depending on type */
10632           switch (p_type)
10633             {
10634             case IPOINTER:
10635             case POINTER:
10636               l = zero;
10637               break;
10638             case FPOINTER:
10639               l = one;
10640               break;
10641             case CPOINTER:
10642               l = "#0x02";
10643               break;
10644             case PPOINTER:
10645               l = "#0x03";
10646               break;
10647
10648             default:
10649               /* this should never happen */
10650               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10651                       "got unknown pointer type");
10652               exit (1);
10653             }
10654           aopPut (AOP (result), l, GPTRSIZE - 1);
10655           goto release;
10656         }
10657
10658       /* just copy the pointers */
10659       size = AOP_SIZE (result);
10660       offset = 0;
10661       _startLazyDPSEvaluation ();
10662       while (size--)
10663         {
10664           aopPut (AOP (result),
10665                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10666                   offset);
10667           offset++;
10668         }
10669       _endLazyDPSEvaluation ();
10670       goto release;
10671     }
10672
10673   /* so we now know that the size of destination is greater
10674      than the size of the source */
10675   /* we move to result for the size of source */
10676   size = AOP_SIZE (right);
10677   offset = 0;
10678   _startLazyDPSEvaluation ();
10679   while (size--)
10680     {
10681       aopPut (AOP (result),
10682               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10683               offset);
10684       offset++;
10685     }
10686   _endLazyDPSEvaluation ();
10687
10688   /* now depending on the sign of the source && destination */
10689   size = AOP_SIZE (result) - AOP_SIZE (right);
10690   /* if unsigned or not an integral type */
10691   /* also, if the source is a bit, we don't need to sign extend, because
10692    * it can't possibly have set the sign bit.
10693    */
10694   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10695     {
10696       while (size--)
10697         {
10698           aopPut (AOP (result), zero, offset++);
10699         }
10700     }
10701   else
10702     {
10703       /* we need to extend the sign :{ */
10704       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10705                         FALSE, FALSE, TRUE);
10706       MOVA (l);
10707       emitcode ("rlc", "a");
10708       emitcode ("subb", "a,acc");
10709       while (size--)
10710         aopPut (AOP (result), "a", offset++);
10711     }
10712
10713   /* we are done hurray !!!! */
10714
10715 release:
10716   freeAsmop (right, NULL, ic, TRUE);
10717   freeAsmop (result, NULL, ic, TRUE);
10718
10719 }
10720
10721 /*-----------------------------------------------------------------*/
10722 /* genDjnz - generate decrement & jump if not zero instrucion      */
10723 /*-----------------------------------------------------------------*/
10724 static int
10725 genDjnz (iCode * ic, iCode * ifx)
10726 {
10727   symbol *lbl, *lbl1;
10728   if (!ifx)
10729     return 0;
10730
10731   /* if the if condition has a false label
10732      then we cannot save */
10733   if (IC_FALSE (ifx))
10734     return 0;
10735
10736   /* if the minus is not of the form
10737      a = a - 1 */
10738   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10739       !IS_OP_LITERAL (IC_RIGHT (ic)))
10740     return 0;
10741
10742   if (operandLitValue (IC_RIGHT (ic)) != 1)
10743     return 0;
10744
10745   /* if the size of this greater than one then no
10746      saving */
10747   if (getSize (operandType (IC_RESULT (ic))) > 1)
10748     return 0;
10749
10750   /* otherwise we can save BIG */
10751   D(emitcode(";", "genDjnz"););
10752
10753   lbl = newiTempLabel (NULL);
10754   lbl1 = newiTempLabel (NULL);
10755
10756   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10757
10758   if (AOP_NEEDSACC(IC_RESULT(ic)))
10759   {
10760       /* If the result is accessed indirectly via
10761        * the accumulator, we must explicitly write
10762        * it back after the decrement.
10763        */
10764       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10765       
10766       if (strcmp(rByte, "a"))
10767       {
10768            /* Something is hopelessly wrong */
10769            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10770                    __FILE__, __LINE__);
10771            /* We can just give up; the generated code will be inefficient,
10772             * but what the hey.
10773             */
10774            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10775            return 0;
10776       }
10777       emitcode ("dec", "%s", rByte);
10778       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10779       emitcode ("jnz", "!tlabel", lbl->key + 100);
10780   }
10781   else if (IS_AOP_PREG (IC_RESULT (ic)))
10782     {
10783       emitcode ("dec", "%s",
10784                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10785       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10786       emitcode ("jnz", "!tlabel", lbl->key + 100);
10787     }
10788   else
10789     {
10790       emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10791                 lbl->key + 100);
10792     }
10793   emitcode ("sjmp", "!tlabel", lbl1->key + 100);
10794   emitcode ("", "!tlabeldef", lbl->key + 100);
10795   emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
10796   emitcode ("", "!tlabeldef", lbl1->key + 100);
10797
10798   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10799   ifx->generated = 1;
10800   return 1;
10801 }
10802
10803 /*-----------------------------------------------------------------*/
10804 /* genReceive - generate code for a receive iCode                  */
10805 /*-----------------------------------------------------------------*/
10806 static void
10807 genReceive (iCode * ic)
10808 {
10809
10810   D (emitcode (";", "genReceive ");
10811     );
10812
10813   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10814       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10815        IS_TRUE_SYMOP (IC_RESULT (ic))))
10816     {
10817       int size = getSize (operandType (IC_RESULT (ic)));
10818       int offset = fReturnSizeDS390 - size;
10819       while (size--)
10820         {
10821           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10822                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10823           offset++;
10824         }
10825       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10826       size = AOP_SIZE (IC_RESULT (ic));
10827       offset = 0;
10828       while (size--)
10829         {
10830           emitcode ("pop", "acc");
10831           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10832         }
10833
10834     }
10835   else
10836     {
10837       _G.accInUse++;
10838       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10839       _G.accInUse--;
10840       assignResultValue (IC_RESULT (ic));
10841     }
10842
10843   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10844 }
10845
10846 /*-----------------------------------------------------------------*/
10847 /* genMemcpyX2X - gen code for memcpy xdata to xdata               */
10848 /*-----------------------------------------------------------------*/
10849 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
10850 {
10851     operand *from , *to , *count;
10852     symbol *lbl;
10853     bitVect *rsave;
10854     int i;
10855
10856     /* we know it has to be 3 parameters */
10857     assert (nparms == 3);
10858     
10859     rsave = newBitVect(16);
10860     /* save DPTR if it needs to be saved */
10861     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10862             if (bitVectBitValue(ic->rMask,i))
10863                     rsave = bitVectSetBit(rsave,i);
10864     }
10865     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10866                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
10867     savermask(rsave);
10868     
10869     to = parms[0];
10870     from = parms[1];
10871     count = parms[2];
10872
10873     aopOp (from, ic->next, FALSE, FALSE);
10874
10875     /* get from into DPTR1 */
10876     emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, TRUE));
10877     emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, TRUE));
10878     if (options.model == MODEL_FLAT24) {
10879         emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, TRUE));
10880     }
10881
10882     freeAsmop (from, NULL, ic, FALSE);
10883     aopOp (to, ic, FALSE, FALSE);
10884     /* get "to" into DPTR */
10885     /* if the operand is already in dptr
10886        then we do nothing else we move the value to dptr */
10887     if (AOP_TYPE (to) != AOP_STR) {
10888         /* if already in DPTR then we need to push */
10889         if (AOP_TYPE(to) == AOP_DPTR) {
10890             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
10891             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
10892             if (options.model == MODEL_FLAT24)
10893                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10894             emitcode ("pop", "dph");
10895             emitcode ("pop", "dpl");        
10896         } else {
10897             _startLazyDPSEvaluation ();
10898             /* if this is remateriazable */
10899             if (AOP_TYPE (to) == AOP_IMMD) {
10900                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
10901             } else {                    /* we need to get it byte by byte */
10902                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
10903                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
10904                 if (options.model == MODEL_FLAT24) {
10905                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
10906                 }
10907             }
10908             _endLazyDPSEvaluation ();
10909         }
10910     }
10911     freeAsmop (to, NULL, ic, FALSE);
10912
10913     aopOp (count, ic->next->next, FALSE,FALSE);
10914     lbl =newiTempLabel(NULL);
10915
10916     /* now for the actual copy */
10917     if (AOP_TYPE(count) == AOP_LIT && 
10918         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
10919         emitcode (";","OH  JOY auto increment with djnz (very fast)");
10920         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
10921         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
10922         emitcode ("","!tlabeldef",lbl->key+100);
10923         if (fromc) {
10924             emitcode ("clr","a");
10925             emitcode ("movc", "a,@a+dptr");
10926         } else 
10927             emitcode ("movx", "a,@dptr");
10928         emitcode ("movx", "@dptr,a");
10929         emitcode ("inc", "dptr");
10930         emitcode ("inc", "dptr");
10931         emitcode ("djnz","b,!tlabel",lbl->key+100);
10932     } else {
10933         symbol *lbl1 = newiTempLabel(NULL);
10934         
10935         emitcode (";"," Auto increment but no djnz");
10936         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
10937         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
10938         emitcode ("mov", "dps,#!constbyte",0x21);       /* Select DPTR2 & auto-toggle. */
10939         emitcode ("","!tlabeldef",lbl->key+100);
10940         if (fromc) {
10941             emitcode ("clr","a");
10942             emitcode ("movc", "a,@a+dptr");
10943         } else 
10944             emitcode ("movx", "a,@dptr");
10945         emitcode ("movx", "@dptr,a");
10946         emitcode ("inc", "dptr");
10947         emitcode ("inc", "dptr");
10948         emitcode ("mov","a,b");
10949         emitcode ("orl","a,_ap");
10950         emitcode ("jz","!tlabel",lbl1->key+100);
10951         emitcode ("mov","a,_ap");
10952         emitcode ("add","a,#!constbyte",0xFF);
10953         emitcode ("mov","_ap,a");
10954         emitcode ("mov","a,b");
10955         emitcode ("addc","a,#!constbyte",0xFF);
10956         emitcode ("mov","b,a");
10957         emitcode ("sjmp","!tlabel",lbl->key+100);
10958         emitcode ("","!tlabeldef",lbl1->key+100);
10959     }
10960     emitcode ("mov", "dps,#0"); 
10961     freeAsmop (count, NULL, ic, FALSE);
10962     unsavermask(rsave);
10963
10964 }
10965
10966 /*-----------------------------------------------------------------*/
10967 /* genMemsetX - gencode for memSetX data                           */
10968 /*-----------------------------------------------------------------*/
10969 static void genMemsetX(iCode *ic, int nparms, operand **parms)
10970 {
10971     operand *to , *val , *count;
10972     symbol *lbl;
10973     char *l;
10974     int i;
10975     bitVect *rsave = NULL;
10976
10977     /* we know it has to be 3 parameters */
10978     assert (nparms == 3);
10979     
10980     to = parms[0];
10981     val = parms[1];
10982     count = parms[2];
10983         
10984     /* save DPTR if it needs to be saved */
10985     rsave = newBitVect(16);
10986     for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
10987             if (bitVectBitValue(ic->rMask,i))
10988                     rsave = bitVectSetBit(rsave,i);
10989     }
10990     rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
10991                                                   ds390_rUmaskForOp (IC_RESULT(ic))));
10992     savermask(rsave);
10993
10994     aopOp (to, ic, FALSE, FALSE);
10995     /* get "to" into DPTR */
10996     /* if the operand is already in dptr
10997        then we do nothing else we move the value to dptr */
10998     if (AOP_TYPE (to) != AOP_STR) {
10999         /* if already in DPTR then we need to push */
11000         if (AOP_TYPE(to) == AOP_DPTR) {
11001             emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, TRUE));
11002             emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, TRUE));
11003             if (options.model == MODEL_FLAT24)
11004                 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11005             emitcode ("pop", "dph");
11006             emitcode ("pop", "dpl");        
11007         } else {
11008             _startLazyDPSEvaluation ();
11009             /* if this is remateriazable */
11010             if (AOP_TYPE (to) == AOP_IMMD) {
11011                 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, FALSE));
11012             } else {                    /* we need to get it byte by byte */
11013                 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, TRUE));
11014                 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, TRUE));
11015                 if (options.model == MODEL_FLAT24) {
11016                     emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, TRUE));
11017                 }
11018             }
11019             _endLazyDPSEvaluation ();
11020         }
11021     }
11022     freeAsmop (to, NULL, ic, FALSE);
11023
11024     aopOp (val, ic->next->next, FALSE,FALSE);
11025     aopOp (count, ic->next->next, FALSE,FALSE);    
11026     lbl =newiTempLabel(NULL);
11027     /* now for the actual copy */
11028     if (AOP_TYPE(count) == AOP_LIT && 
11029         (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11030         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11031         emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,FALSE));
11032         MOVA(l);
11033         emitcode ("","!tlabeldef",lbl->key+100);
11034         emitcode ("movx", "@dptr,a");
11035         emitcode ("inc", "dptr");
11036         emitcode ("djnz","b,!tlabel",lbl->key+100);
11037     } else {
11038         symbol *lbl1 = newiTempLabel(NULL);
11039         
11040         emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, TRUE));
11041         emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, TRUE));
11042         emitcode ("","!tlabeldef",lbl->key+100);
11043         l = aopGet(AOP (val), 0, FALSE, FALSE, TRUE);
11044         MOVA(l);
11045         emitcode ("movx", "a,@dptr");
11046         emitcode ("inc", "dptr");
11047         emitcode ("mov","a,b");
11048         emitcode ("orl","a,_ap");
11049         emitcode ("jz","!tlabel",lbl1->key+100);
11050         emitcode ("mov","a,_ap");
11051         emitcode ("add","a,#!constbyte",0xFF);
11052         emitcode ("mov","_ap,a");
11053         emitcode ("mov","a,b");
11054         emitcode ("addc","a,#!constbyte",0xFF);
11055         emitcode ("mov","b,a");
11056         emitcode ("sjmp","!tlabel",lbl->key+100);
11057         emitcode ("","!tlabeldef",lbl1->key+100);
11058     }
11059     freeAsmop (count, NULL, ic, FALSE);
11060     unsavermask(rsave);
11061 }
11062
11063 /*-----------------------------------------------------------------*/
11064 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11065 /*-----------------------------------------------------------------*/
11066 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11067 {
11068         bitVect *rsave ;
11069         operand *pnum, *result;
11070         int i;
11071     
11072         assert (nparms==1);
11073         /* save registers that need to be saved */
11074         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11075                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11076     
11077         pnum = parms[0]; 
11078         aopOp (pnum, ic, FALSE, FALSE);
11079         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11080         freeAsmop (pnum, NULL, ic, FALSE);
11081         emitcode ("lcall","NatLib_LoadPrimitive");
11082         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11083         if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) || 
11084             aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
11085                 for (i = (size-1) ; i >= 0 ; i-- ) {
11086                         emitcode ("push","a%s",javaRet[i]);
11087                 }
11088                 for (i=0; i < size ; i++ ) {
11089                         emitcode ("pop","a%s",aopGet(AOP(result),i,FALSE,FALSE,FALSE));
11090                 }
11091         } else {
11092                 for (i = 0 ; i < size ; i++ ) {
11093                         aopPut(AOP(result),javaRet[i],i);
11094                 }
11095         }    
11096         freeAsmop (result, NULL, ic, FALSE);
11097         unsavermask(rsave);
11098 }
11099
11100 /*-----------------------------------------------------------------*/
11101 /* genNatLibLoadPointer - calls TINI api function to load pointer  */
11102 /*-----------------------------------------------------------------*/
11103 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
11104 {
11105         bitVect *rsave ;
11106         operand *pnum, *result;
11107         int size = 3;
11108         int i;
11109     
11110         assert (nparms==1);
11111         /* save registers that need to be saved */
11112         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11113                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11114     
11115         pnum = parms[0]; 
11116         aopOp (pnum, ic, FALSE, FALSE);
11117         emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,FALSE));
11118         freeAsmop (pnum, NULL, ic, FALSE);
11119         emitcode ("lcall","NatLib_LoadPointer");
11120         aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11121         if (AOP_TYPE(result)!=AOP_STR) {
11122                 for (i = 0 ; i < size ; i++ ) {
11123                         aopPut(AOP(result),fReturn[i],i);
11124                 }
11125         }    
11126         freeAsmop (result, NULL, ic, FALSE);
11127         unsavermask(rsave);
11128 }
11129
11130 /*-----------------------------------------------------------------*/
11131 /* genNatLibInstallStateBlock -                                    */
11132 /*-----------------------------------------------------------------*/
11133 static void genNatLibInstallStateBlock(iCode *ic, int nparms, 
11134                                        operand **parms, const char *name)
11135 {
11136         bitVect *rsave ;
11137         operand *psb, *handle;
11138         assert (nparms==2);
11139
11140         /* save registers that need to be saved */
11141         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11142                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11143         psb = parms[0];
11144         handle = parms[1];
11145
11146         /* put pointer to state block into DPTR1 */
11147         aopOp (psb, ic, FALSE, FALSE);
11148         if (AOP_TYPE (psb) == AOP_IMMD) {
11149                 emitcode ("mov","dps,#1");
11150                 emitcode ("mov", "dptr,%s", aopGet (AOP (psb), 0, TRUE, FALSE, FALSE));
11151                 emitcode ("mov","dps,#0");
11152         } else {
11153                 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,FALSE));
11154                 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,FALSE));
11155                 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,FALSE));
11156         }
11157         freeAsmop (psb, NULL, ic, FALSE);
11158
11159         /* put libraryID into DPTR */
11160         emitcode ("mov","dptr,#LibraryID");
11161
11162         /* put handle into r3:r2 */
11163         aopOp (handle, ic, FALSE, FALSE);
11164         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11165                 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));  
11166                 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11167                 emitcode ("pop","ar3");
11168                 emitcode ("pop","ar2");
11169         } else {        
11170                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));        
11171                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11172         }
11173         freeAsmop (psb, NULL, ic, FALSE);
11174
11175         /* make the call */
11176         emitcode ("lcall","NatLib_Install%sStateBlock",name);
11177
11178         /* put return value into place*/
11179         _G.accInUse++;
11180         aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
11181         _G.accInUse--;
11182         aopPut(AOP(IC_RESULT(ic)),"a",0);
11183         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11184         unsavermask(rsave);
11185 }
11186
11187 /*-----------------------------------------------------------------*/
11188 /* genNatLibRemoveStateBlock -                                     */
11189 /*-----------------------------------------------------------------*/
11190 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
11191 {
11192         bitVect *rsave ;
11193
11194         assert(nparms==0);
11195
11196         /* save registers that need to be saved */
11197         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11198                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11199
11200         /* put libraryID into DPTR */
11201         emitcode ("mov","dptr,#LibraryID");
11202         /* make the call */
11203         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11204         unsavermask(rsave);
11205 }
11206
11207 /*-----------------------------------------------------------------*/
11208 /* genNatLibGetStateBlock -                                        */
11209 /*-----------------------------------------------------------------*/
11210 static void genNatLibGetStateBlock(iCode *ic,int nparms,
11211                                    operand **parms,const char *name)
11212 {
11213         bitVect *rsave ;
11214         symbol *lbl = newiTempLabel(NULL);
11215         
11216         assert(nparms==0);
11217         /* save registers that need to be saved */
11218         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11219                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11220
11221         /* put libraryID into DPTR */
11222         emitcode ("mov","dptr,#LibraryID");
11223         /* make the call */
11224         emitcode ("lcall","NatLib_Remove%sStateBlock",name);
11225         emitcode ("jnz","!tlabel",lbl->key+100);
11226
11227         /* put return value into place */
11228         aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11229         if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11230                 emitcode ("push","ar3");
11231                 emitcode ("push","ar2");
11232                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11233                 emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11234         } else {
11235                 aopPut(AOP(IC_RESULT(ic)),"r2",0);
11236                 aopPut(AOP(IC_RESULT(ic)),"r3",1);
11237         }
11238         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11239         emitcode ("","!tlabeldef",lbl->key+100);
11240         unsavermask(rsave);
11241 }
11242
11243 /*-----------------------------------------------------------------*/
11244 /* genMMMalloc -                                                   */
11245 /*-----------------------------------------------------------------*/
11246 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
11247                          int size, const char *name)
11248 {
11249         bitVect *rsave ;
11250         operand *bsize;
11251         symbol *rsym;
11252         symbol *lbl = newiTempLabel(NULL);
11253
11254         assert (nparms == 1);
11255         /* save registers that need to be saved */
11256         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11257                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11258         
11259         bsize=parms[0];
11260         aopOp (bsize,ic,FALSE,FALSE);
11261
11262         /* put the size in R4-R2 */
11263         if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
11264                 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11265                 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11266                 if (size==3) {
11267                         emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11268                         emitcode("pop","ar4");
11269                 }
11270                 emitcode("pop","ar3");
11271                 emitcode("pop","ar2");          
11272         } else {
11273                 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,FALSE));
11274                 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,FALSE));
11275                 if (size==3) {
11276                         emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,FALSE));
11277                 }
11278         }
11279         freeAsmop (bsize, NULL, ic, FALSE);
11280
11281         /* make the call */
11282         emitcode ("lcall","MM_%s",name);
11283         emitcode ("jz","!tlabel",lbl->key+100);
11284         emitcode ("mov","r2,#!constbyte",0xff);
11285         emitcode ("mov","r3,#!constbyte",0xff);
11286         emitcode ("","!tlabeldef",lbl->key+100);
11287         /* we don't care about the pointer : we just save the handle */
11288         rsym = OP_SYMBOL(IC_RESULT(ic));
11289         if (rsym->liveFrom != rsym->liveTo) {
11290                 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
11291                 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
11292                         emitcode ("push","ar3");
11293                         emitcode ("push","ar2");
11294                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,FALSE));
11295                         emitcode ("pop","%s",aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,FALSE));
11296                 } else {
11297                         aopPut(AOP(IC_RESULT(ic)),"r2",0);
11298                         aopPut(AOP(IC_RESULT(ic)),"r3",1);
11299                 }
11300                 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11301         }
11302         unsavermask(rsave);
11303 }
11304
11305 /*-----------------------------------------------------------------*/
11306 /* genMMDeref -                                                    */
11307 /*-----------------------------------------------------------------*/
11308 static void genMMDeref (iCode *ic,int nparms, operand **parms)
11309 {
11310         bitVect *rsave ;
11311         operand *handle;
11312
11313         assert (nparms == 1);
11314         /* save registers that need to be saved */
11315         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11316                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11317         
11318         handle=parms[0];
11319         aopOp (handle,ic,FALSE,FALSE);
11320
11321         /* put the size in R4-R2 */
11322         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11323                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11324                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11325                 emitcode("pop","ar3");
11326                 emitcode("pop","ar2");          
11327         } else {
11328                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11329                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11330         }
11331         freeAsmop (handle, NULL, ic, FALSE);
11332
11333         /* make the call */
11334         emitcode ("lcall","MM_Deref");
11335         
11336         {
11337                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11338                 if (rsym->liveFrom != rsym->liveTo) {                   
11339                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11340                         if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
11341                                 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
11342                                 aopPut(AOP(IC_RESULT(ic)),"dph",1);
11343                                 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
11344                         }
11345                 }
11346         }
11347         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11348         unsavermask(rsave);
11349 }
11350
11351 /*-----------------------------------------------------------------*/
11352 /* genMMUnrestrictedPersist -                                      */
11353 /*-----------------------------------------------------------------*/
11354 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
11355 {
11356         bitVect *rsave ;
11357         operand *handle;
11358
11359         assert (nparms == 1);
11360         /* save registers that need to be saved */
11361         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11362                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11363         
11364         handle=parms[0];
11365         aopOp (handle,ic,FALSE,FALSE);
11366
11367         /* put the size in R3-R2 */
11368         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11369                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11370                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11371                 emitcode("pop","ar3");
11372                 emitcode("pop","ar2");          
11373         } else {
11374                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11375                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11376         }
11377         freeAsmop (handle, NULL, ic, FALSE);
11378
11379         /* make the call */
11380         emitcode ("lcall","MM_UnrestrictedPersist");
11381
11382         {
11383                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11384                 if (rsym->liveFrom != rsym->liveTo) {   
11385                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11386                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11387                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11388                 }
11389         }
11390         unsavermask(rsave);
11391 }
11392
11393 /*-----------------------------------------------------------------*/
11394 /* genSystemExecJavaProcess -                                      */
11395 /*-----------------------------------------------------------------*/
11396 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
11397 {
11398         bitVect *rsave ;
11399         operand *handle, *pp;
11400
11401         assert (nparms==2);
11402         /* save registers that need to be saved */
11403         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11404                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11405         
11406         pp = parms[0];
11407         handle = parms[1];
11408         
11409         /* put the handle in R3-R2 */
11410         aopOp (handle,ic,FALSE,FALSE);
11411         if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
11412                 emitcode("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11413                 emitcode("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11414                 emitcode("pop","ar3");
11415                 emitcode("pop","ar2");          
11416         } else {
11417                 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,FALSE));
11418                 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,FALSE));
11419         }
11420         freeAsmop (handle, NULL, ic, FALSE);
11421         
11422         /* put pointer in DPTR */
11423         aopOp (pp,ic,FALSE,FALSE);
11424         if (AOP_TYPE(pp) == AOP_IMMD) {
11425                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));          
11426         } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
11427                 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11428                 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11429                 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11430         }
11431         freeAsmop (handle, NULL, ic, FALSE);
11432
11433         /* make the call */
11434         emitcode ("lcall","System_ExecJavaProcess");
11435         
11436         /* put result in place */
11437         {
11438                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11439                 if (rsym->liveFrom != rsym->liveTo) {   
11440                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11441                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11442                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11443                 }
11444         }
11445         
11446         unsavermask(rsave);
11447 }
11448
11449 /*-----------------------------------------------------------------*/
11450 /* genSystemRTCRegisters -                                         */
11451 /*-----------------------------------------------------------------*/
11452 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
11453                                   char *name)
11454 {
11455         bitVect *rsave ;
11456         operand *pp;
11457
11458         assert (nparms==1);
11459         /* save registers that need to be saved */
11460         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11461                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11462         
11463         pp=parms[0];
11464         /* put pointer in DPTR */
11465         aopOp (pp,ic,FALSE,FALSE);
11466         if (AOP_TYPE (pp) == AOP_IMMD) {
11467                 emitcode ("mov","dps,#1");
11468                 emitcode ("mov", "dptr,%s", aopGet (AOP (pp), 0, TRUE, FALSE, FALSE));
11469                 emitcode ("mov","dps,#0");
11470         } else {
11471                 emitcode ("mov","dpl1,%s",aopGet(AOP(pp),0,FALSE,FALSE,FALSE));
11472                 emitcode ("mov","dph1,%s",aopGet(AOP(pp),1,FALSE,FALSE,FALSE));
11473                 emitcode ("mov","dpx1,%s",aopGet(AOP(pp),2,FALSE,FALSE,FALSE));
11474         }
11475         freeAsmop (pp, NULL, ic, FALSE);
11476
11477         /* make the call */
11478         emitcode ("lcall","System_%sRTCRegisters",name);
11479
11480         unsavermask(rsave);
11481 }
11482
11483 /*-----------------------------------------------------------------*/
11484 /* genSystemThreadSleep -                                          */
11485 /*-----------------------------------------------------------------*/
11486 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
11487 {
11488         bitVect *rsave ;
11489         operand *to, *s;
11490
11491         assert (nparms==1);
11492         /* save registers that need to be saved */
11493         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11494                                          ds390_rUmaskForOp (IC_RESULT(ic))));   
11495
11496         to = parms[0];
11497         aopOp(to,ic,FALSE,FALSE);
11498         if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
11499             aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
11500                 emitcode ("push","%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11501                 emitcode ("push","%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11502                 emitcode ("push","%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11503                 emitcode ("push","%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11504                 emitcode ("pop","ar3");
11505                 emitcode ("pop","ar2");
11506                 emitcode ("pop","ar1");
11507                 emitcode ("pop","ar0");
11508         } else {
11509                 emitcode ("mov","r0,%s",aopGet(AOP(to),0,FALSE,TRUE,FALSE));
11510                 emitcode ("mov","r1,%s",aopGet(AOP(to),1,FALSE,TRUE,FALSE));
11511                 emitcode ("mov","r2,%s",aopGet(AOP(to),2,FALSE,TRUE,FALSE));
11512                 emitcode ("mov","r3,%s",aopGet(AOP(to),3,FALSE,TRUE,FALSE));
11513         }
11514         freeAsmop (to, NULL, ic, FALSE);
11515
11516         /* suspend in acc */
11517         s = parms[1];
11518         aopOp(s,ic,FALSE,FALSE);
11519         emitcode ("mov","a,%s",aopGet(AOP(s),0,FALSE,TRUE,FALSE));
11520         freeAsmop (s, NULL, ic, FALSE);
11521
11522         /* make the call */
11523         emitcode ("lcall","System_%s",name);
11524
11525         unsavermask(rsave);
11526 }
11527
11528 /*-----------------------------------------------------------------*/
11529 /* genSystemThreadResume -                                         */
11530 /*-----------------------------------------------------------------*/
11531 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
11532 {
11533         bitVect *rsave ;
11534         operand *tid,*pid;
11535
11536         assert (nparms==2);
11537         /* save registers that need to be saved */
11538         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11539                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11540         
11541         tid = parms[0];
11542         pid = parms[1];
11543         
11544         /* PID in R0 */
11545         aopOp(pid,ic,FALSE,FALSE);
11546         emitcode ("mov","r0,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11547         freeAsmop (pid, NULL, ic, FALSE);
11548         
11549         /* tid into ACC */
11550         aopOp(tid,ic,FALSE,FALSE);
11551         emitcode ("mov","a,%s",aopGet(AOP(tid),0,FALSE,TRUE,FALSE));
11552         freeAsmop (tid, NULL, ic, FALSE);
11553         
11554         emitcode ("lcall","System_ThreadResume");
11555
11556         /* put result into place */
11557         {
11558                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11559                 if (rsym->liveFrom != rsym->liveTo) {   
11560                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11561                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11562                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11563                 }
11564         }
11565         unsavermask(rsave);
11566 }
11567
11568 /*-----------------------------------------------------------------*/
11569 /* genSystemProcessResume -                                        */
11570 /*-----------------------------------------------------------------*/
11571 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
11572 {
11573         bitVect *rsave ;
11574         operand *pid;
11575
11576         assert (nparms==1);
11577         /* save registers that need to be saved */
11578         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11579                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11580         
11581         pid = parms[0];
11582         
11583         /* pid into ACC */
11584         aopOp(pid,ic,FALSE,FALSE);
11585         emitcode ("mov","a,%s",aopGet(AOP(pid),0,FALSE,TRUE,FALSE));
11586         freeAsmop (pid, NULL, ic, FALSE);
11587         
11588         emitcode ("lcall","System_ProcessResume");
11589
11590         unsavermask(rsave);
11591 }
11592
11593 /*-----------------------------------------------------------------*/
11594 /* genSystem -                                                     */
11595 /*-----------------------------------------------------------------*/
11596 static void genSystem (iCode *ic,int nparms,char *name)
11597 {
11598         assert(nparms == 0);
11599
11600         emitcode ("lcall","System_%s",name);
11601 }
11602
11603 /*-----------------------------------------------------------------*/
11604 /* genSystemPoll -                                                  */
11605 /*-----------------------------------------------------------------*/
11606 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
11607 {
11608         bitVect *rsave ;
11609         operand *fp;
11610
11611         assert (nparms==1);
11612         /* save registers that need to be saved */
11613         savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11614                                          ds390_rUmaskForOp (IC_RESULT(ic))));
11615
11616         fp = parms[0];
11617         aopOp (fp,ic,FALSE,FALSE);
11618         if (AOP_TYPE (fp) == AOP_IMMD) {
11619                 emitcode ("mov", "dptr,%s", aopGet (AOP (fp), 0, TRUE, FALSE, FALSE));
11620         } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
11621                 emitcode ("mov","dpl,%s",aopGet(AOP(fp),0,FALSE,FALSE,FALSE));
11622                 emitcode ("mov","dph,%s",aopGet(AOP(fp),1,FALSE,FALSE,FALSE));
11623                 emitcode ("mov","dpx,%s",aopGet(AOP(fp),2,FALSE,FALSE,FALSE));
11624         }
11625         freeAsmop (fp, NULL, ic, FALSE);
11626
11627         emitcode ("lcall","System_%sPoll",name);
11628
11629         /* put result into place */
11630         {
11631                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11632                 if (rsym->liveFrom != rsym->liveTo) {   
11633                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11634                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11635                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11636                 }
11637         }
11638         unsavermask(rsave);
11639 }
11640
11641 /*-----------------------------------------------------------------*/
11642 /* genSystemGetCurrentID -                                         */
11643 /*-----------------------------------------------------------------*/
11644 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
11645 {
11646         assert (nparms==0);
11647
11648         emitcode ("lcall","System_GetCurrent%sId",name);
11649         /* put result into place */
11650         {
11651                 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
11652                 if (rsym->liveFrom != rsym->liveTo) {   
11653                         aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
11654                         aopPut(AOP(IC_RESULT(ic)),"a",0);
11655                         freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11656                 }
11657         }
11658 }
11659
11660 /*-----------------------------------------------------------------*/
11661 /* genBuiltIn - calls the appropriate function to  generating code */
11662 /* for a built in function                                         */
11663 /*-----------------------------------------------------------------*/
11664 static void genBuiltIn (iCode *ic)
11665 {
11666         operand *bi_parms[MAX_BUILTIN_ARGS];
11667         int nbi_parms;
11668         iCode *bi_iCode;
11669         symbol *bif;
11670
11671         /* get all the arguments for a built in function */
11672         bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
11673
11674         /* which function is it */
11675         bif = OP_SYMBOL(IC_LEFT(bi_iCode));
11676         if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
11677                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
11678         } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
11679                 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
11680         } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
11681                 genMemsetX(bi_iCode,nbi_parms,bi_parms);
11682         } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
11683                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
11684         } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
11685                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
11686         } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
11687                 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
11688         } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
11689                 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
11690         } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
11691                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11692         } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
11693                 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11694         } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
11695                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
11696         } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
11697                 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
11698         } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
11699                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
11700         } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
11701                 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
11702         } else if (strcmp(bif->name,"MM_XMalloc")==0) {
11703                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
11704         } else if (strcmp(bif->name,"MM_Malloc")==0) {
11705                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
11706         } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
11707                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
11708         } else if (strcmp(bif->name,"MM_Free")==0) {
11709                 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
11710         } else if (strcmp(bif->name,"MM_Deref")==0) {
11711                 genMMDeref(bi_iCode,nbi_parms,bi_parms);
11712         } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
11713                 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
11714         } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
11715                 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
11716         } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
11717                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
11718         } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
11719                 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
11720         } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
11721                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
11722         } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
11723                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
11724         } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
11725                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
11726         } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
11727                 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
11728         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11729                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11730         } else if (strcmp(bif->name,"System_SaveThread")==0) {
11731                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11732         } else if (strcmp(bif->name,"System_ThreadResume")==0) {
11733                 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
11734         } else if (strcmp(bif->name,"System_ProcessResume")==0) {
11735                 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
11736         } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
11737                 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
11738         } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
11739                 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
11740         } else if (strcmp(bif->name,"System_ProcessYield")==0) {
11741                 genSystem(bi_iCode,nbi_parms,"ProcessYield");
11742         } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
11743                 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
11744         } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
11745                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
11746         } else if (strcmp(bif->name,"System_RemovePoll")==0) {
11747                 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
11748         } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
11749                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
11750         } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
11751                 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
11752         } else {
11753                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
11754                 return ;
11755         }
11756         return ;    
11757 }
11758
11759 /*-----------------------------------------------------------------*/
11760 /* gen390Code - generate code for Dallas 390 based controllers     */
11761 /*-----------------------------------------------------------------*/
11762 void
11763 gen390Code (iCode * lic)
11764 {
11765   iCode *ic;
11766   int cln = 0;
11767
11768   lineHead = lineCurr = NULL;
11769
11770   if (options.model == MODEL_FLAT24) {
11771     fReturnSizeDS390 = 5;
11772     fReturn = fReturn24;
11773   } else {
11774     fReturnSizeDS390 = 4;
11775     fReturn = fReturn16;
11776     options.stack10bit=0;
11777   }
11778 #if 0
11779   //REMOVE ME!!!
11780   /* print the allocation information */
11781   if (allocInfo)
11782     printAllocInfo (currFunc, codeOutFile);
11783 #endif
11784   /* if debug information required */
11785   if (options.debug && currFunc)
11786     {
11787       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
11788       _G.debugLine = 1;
11789       if (IS_STATIC (currFunc->etype))
11790         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
11791       else
11792         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
11793       _G.debugLine = 0;
11794     }
11795   /* stack pointer name */
11796   if (options.useXstack)
11797     spname = "_spx";
11798   else
11799     spname = "sp";
11800
11801
11802   for (ic = lic; ic; ic = ic->next)
11803     {
11804
11805       if (cln != ic->lineno)
11806         {
11807           if (options.debug)
11808             {
11809               _G.debugLine = 1;
11810               emitcode ("", "C$%s$%d$%d$%d ==.",
11811                         FileBaseName (ic->filename), ic->lineno,
11812                         ic->level, ic->block);
11813               _G.debugLine = 0;
11814             }
11815           emitcode (";", "%s %d", ic->filename, ic->lineno);
11816           cln = ic->lineno;
11817         }
11818       /* if the result is marked as
11819          spilt and rematerializable or code for
11820          this has already been generated then
11821          do nothing */
11822       if (resultRemat (ic) || ic->generated)
11823         continue;
11824
11825       /* depending on the operation */
11826       switch (ic->op)
11827         {
11828         case '!':
11829           genNot (ic);
11830           break;
11831
11832         case '~':
11833           genCpl (ic);
11834           break;
11835
11836         case UNARYMINUS:
11837           genUminus (ic);
11838           break;
11839
11840         case IPUSH:
11841           genIpush (ic);
11842           break;
11843
11844         case IPOP:
11845           /* IPOP happens only when trying to restore a
11846              spilt live range, if there is an ifx statement
11847              following this pop then the if statement might
11848              be using some of the registers being popped which
11849              would destory the contents of the register so
11850              we need to check for this condition and handle it */
11851           if (ic->next &&
11852               ic->next->op == IFX &&
11853               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11854             genIfx (ic->next, ic);
11855           else
11856             genIpop (ic);
11857           break;
11858
11859         case CALL:
11860           genCall (ic);
11861           break;
11862
11863         case PCALL:
11864           genPcall (ic);
11865           break;
11866
11867         case FUNCTION:
11868           genFunction (ic);
11869           break;
11870
11871         case ENDFUNCTION:
11872           genEndFunction (ic);
11873           break;
11874
11875         case RETURN:
11876           genRet (ic);
11877           break;
11878
11879         case LABEL:
11880           genLabel (ic);
11881           break;
11882
11883         case GOTO:
11884           genGoto (ic);
11885           break;
11886
11887         case '+':
11888           genPlus (ic);
11889           break;
11890
11891         case '-':
11892           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11893             genMinus (ic);
11894           break;
11895
11896         case '*':
11897           genMult (ic);
11898           break;
11899
11900         case '/':
11901           genDiv (ic);
11902           break;
11903
11904         case '%':
11905           genMod (ic);
11906           break;
11907
11908         case '>':
11909           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11910           break;
11911
11912         case '<':
11913           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11914           break;
11915
11916         case LE_OP:
11917         case GE_OP:
11918         case NE_OP:
11919
11920           /* note these two are xlated by algebraic equivalence
11921              during parsing SDCC.y */
11922           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11923                   "got '>=' or '<=' shouldn't have come here");
11924           break;
11925
11926         case EQ_OP:
11927           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11928           break;
11929
11930         case AND_OP:
11931           genAndOp (ic);
11932           break;
11933
11934         case OR_OP:
11935           genOrOp (ic);
11936           break;
11937
11938         case '^':
11939           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11940           break;
11941
11942         case '|':
11943           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11944           break;
11945
11946         case BITWISEAND:
11947           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11948           break;
11949
11950         case INLINEASM:
11951           genInline (ic);
11952           break;
11953
11954         case RRC:
11955           genRRC (ic);
11956           break;
11957
11958         case RLC:
11959           genRLC (ic);
11960           break;
11961
11962         case GETHBIT:
11963           genGetHbit (ic);
11964           break;
11965
11966         case LEFT_OP:
11967           genLeftShift (ic);
11968           break;
11969
11970         case RIGHT_OP:
11971           genRightShift (ic);
11972           break;
11973
11974         case GET_VALUE_AT_ADDRESS:
11975           genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_LEFT(ic)))));
11976           break;
11977
11978         case '=':
11979           if (POINTER_SET (ic))
11980             genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11981           else
11982             genAssign (ic);
11983           break;
11984
11985         case IFX:
11986           genIfx (ic, NULL);
11987           break;
11988
11989         case ADDRESS_OF:
11990           genAddrOf (ic);
11991           break;
11992
11993         case JUMPTABLE:
11994           genJumpTab (ic);
11995           break;
11996
11997         case CAST:
11998           genCast (ic);
11999           break;
12000
12001         case RECEIVE:
12002           genReceive (ic);
12003           break;
12004
12005         case SEND:
12006           if (ic->builtinSEND) genBuiltIn(ic);
12007           else addSet (&_G.sendSet, ic);
12008           break;
12009
12010         case ARRAYINIT:
12011             genArrayInit(ic);
12012             break;
12013             
12014         default:
12015           ic = ic;
12016         }
12017     }
12018
12019
12020   /* now we are ready to call the
12021      peep hole optimizer */
12022   if (!options.nopeep)
12023     peepHole (&lineHead);
12024
12025   /* now do the actual printing */
12026   printLine (lineHead, codeOutFile);
12027   return;
12028 }