fixed bug #478698
[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 = "#0x00";
66 static char *one = "#0x01";
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
83 static short rbank = -1;
84
85 static struct
86   {
87     short r0Pushed;
88     short r1Pushed;
89     short accInUse;
90     short inLine;
91     short debugLine;
92     short nRegsSaved;
93     set *sendSet;
94   }
95 _G;
96
97 static void saveRBank (int, iCode *, bool);
98
99 #define RESULTONSTACK(x) \
100                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
101                          IC_RESULT(x)->aop->type == AOP_STK )
102
103 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
104 #define MOVA(x) { char *_mova_tmp = strdup(x); \
105                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
106                  { \
107                     emitcode("mov","a,%s",_mova_tmp); \
108                  } \
109                  free(_mova_tmp); \
110                 }
111 #define CLRC    emitcode("clr","c")
112 #define SETC    emitcode("setb","c")
113
114 // A scratch register which will be used to hold
115 // result bytes from operands in far space via DPTR2.
116 #define DP2_RESULT_REG  "ap"
117
118 static lineNode *lineHead = NULL;
119 static lineNode *lineCurr = NULL;
120
121 static unsigned char SLMask[] =
122 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
123  0xE0, 0xC0, 0x80, 0x00};
124 static unsigned char SRMask[] =
125 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
126  0x07, 0x03, 0x01, 0x00};
127
128 #define LSB     0
129 #define MSB16   1
130 #define MSB24   2
131 #define MSB32   3
132
133 /*-----------------------------------------------------------------*/
134 /* emitcode - writes the code into a file : for now it is simple    */
135 /*-----------------------------------------------------------------*/
136 static void
137 emitcode (char *inst, char *fmt,...)
138 {
139   va_list ap;
140   char lb[INITIAL_INLINEASM];
141   char *lbp = lb;
142
143   va_start (ap, fmt);
144
145   if (inst && *inst)
146     {
147       if (fmt && *fmt)
148         sprintf (lb, "%s\t", inst);
149       else
150         sprintf (lb, "%s", inst);
151       vsprintf (lb + (strlen (lb)), fmt, ap);
152     }
153   else
154     vsprintf (lb, fmt, ap);
155
156   while (isspace (*lbp))
157     lbp++;
158
159   if (lbp && *lbp)
160     lineCurr = (lineCurr ?
161                 connectLine (lineCurr, newLineNode (lb)) :
162                 (lineHead = newLineNode (lb)));
163   lineCurr->isInline = _G.inLine;
164   lineCurr->isDebug = _G.debugLine;
165   va_end (ap);
166 }
167
168 /*-----------------------------------------------------------------*/
169 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
170 /*-----------------------------------------------------------------*/
171 static regs *
172 getFreePtr (iCode * ic, asmop ** aopp, bool result)
173 {
174   bool r0iu = FALSE, r1iu = FALSE;
175   bool r0ou = FALSE, r1ou = FALSE;
176
177   /* the logic: if r0 & r1 used in the instruction
178      then we are in trouble otherwise */
179
180   /* first check if r0 & r1 are used by this
181      instruction, in which case we are in trouble */
182   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
183   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
184   if (r0iu && r1iu) {
185       goto endOfWorld;
186     }
187
188   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
189   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
190
191   /* if no usage of r0 then return it */
192   if (!r0iu && !r0ou)
193     {
194       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
195       (*aopp)->type = AOP_R0;
196
197       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
198     }
199
200   /* if no usage of r1 then return it */
201   if (!r1iu && !r1ou)
202     {
203       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
204       (*aopp)->type = AOP_R1;
205
206       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
207     }
208
209   /* now we know they both have usage */
210   /* if r0 not used in this instruction */
211   if (!r0iu)
212     {
213       /* push it if not already pushed */
214       if (!_G.r0Pushed)
215         {
216           emitcode ("push", "%s",
217                     ds390_regWithIdx (R0_IDX)->dname);
218           _G.r0Pushed++;
219         }
220
221       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
222       (*aopp)->type = AOP_R0;
223
224       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
225     }
226
227   /* if r1 not used then */
228
229   if (!r1iu)
230     {
231       /* push it if not already pushed */
232       if (!_G.r1Pushed)
233         {
234           emitcode ("push", "%s",
235                     ds390_regWithIdx (R1_IDX)->dname);
236           _G.r1Pushed++;
237         }
238
239       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
240       (*aopp)->type = AOP_R1;
241       return ds390_regWithIdx (R1_IDX);
242     }
243
244 endOfWorld:
245   /* I said end of world but not quite end of world yet */
246   /* if this is a result then we can push it on the stack */
247   if (result)
248     {
249       (*aopp)->type = AOP_STK;
250       return NULL;
251     }
252
253   /* other wise this is true end of the world */
254   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
255           "getFreePtr should never reach here");
256   exit (1);
257 }
258
259 /*-----------------------------------------------------------------*/
260 /* newAsmop - creates a new asmOp                                  */
261 /*-----------------------------------------------------------------*/
262 static asmop *
263 newAsmop (short type)
264 {
265   asmop *aop;
266
267   aop = Safe_calloc (1, sizeof (asmop));
268   aop->type = type;
269   return aop;
270 }
271
272 static int _currentDPS;         /* Current processor DPS. */
273 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
274 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
275
276 /*-----------------------------------------------------------------*/
277 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
278 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
279 /* alternate DPTR (DPL1/DPH1/DPX1).          */
280 /*-----------------------------------------------------------------*/
281 static void
282 genSetDPTR (int n)
283 {
284
285   /* If we are doing lazy evaluation, simply note the desired
286    * change, but don't emit any code yet.
287    */
288   if (_lazyDPS)
289     {
290       _desiredDPS = n;
291       return;
292     }
293
294   if (!n)
295     {
296       emitcode ("mov", "dps, #0x00");
297     }
298   else
299     {
300       TR_DPTR("#1");
301       emitcode ("mov", "dps, #0x01");
302     }
303 }
304
305 /*-----------------------------------------------------------------*/
306 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
307 /*                   */
308 /* Any code that operates on DPTR (NB: not on the individual     */
309 /* components, like DPH) *must* call _flushLazyDPS() before using  */
310 /* DPTR within a lazy DPS evaluation block.        */
311 /*                   */
312 /* Note that aopPut and aopGet already contain the proper calls to */
313 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
314 /* DPS evaluation block.             */
315 /*                   */
316 /* Also, _flushLazyDPS must be called before any flow control      */
317 /* operations that could potentially branch out of the block.    */
318 /*                         */
319 /* Lazy DPS evaluation is simply an optimization (though an      */
320 /* important one), so if in doubt, leave it out.       */
321 /*-----------------------------------------------------------------*/
322 static void
323 _startLazyDPSEvaluation (void)
324 {
325   _currentDPS = 0;
326   _desiredDPS = 0;
327 #ifdef BETTER_LITERAL_SHIFT  
328   _lazyDPS++;
329 #else
330   _lazyDPS = 1;
331 #endif  
332 }
333
334 /*-----------------------------------------------------------------*/
335 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
336 /* desired one. Call before using DPTR within a lazy DPS evaluation */
337 /* block.                */
338 /*-----------------------------------------------------------------*/
339 static void
340 _flushLazyDPS (void)
341 {
342   if (!_lazyDPS)
343     {
344       /* nothing to do. */
345       return;
346     }
347
348   if (_desiredDPS != _currentDPS)
349     {
350       if (_desiredDPS)
351         {
352           emitcode ("inc", "dps");
353         }
354       else
355         {
356           emitcode ("dec", "dps");
357         }
358       _currentDPS = _desiredDPS;
359     }
360 }
361
362 /*-----------------------------------------------------------------*/
363 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
364 /*                   */
365 /* Forces us back to the safe state (standard DPTR selected).    */
366 /*-----------------------------------------------------------------*/
367 static void
368 _endLazyDPSEvaluation (void)
369 {
370 #ifdef BETTER_LITERAL_SHIFT  
371   _lazyDPS--;
372 #else
373   _lazyDPS = 0;
374 #endif    
375   if (!_lazyDPS)
376   {
377     if (_currentDPS)
378     {
379       genSetDPTR (0);
380       _flushLazyDPS ();
381     }
382     _currentDPS = 0;
383     _desiredDPS = 0;
384   }
385 }
386
387
388
389 /*-----------------------------------------------------------------*/
390 /* pointerCode - returns the code for a pointer type               */
391 /*-----------------------------------------------------------------*/
392 static int
393 pointerCode (sym_link * etype)
394 {
395
396   return PTR_TYPE (SPEC_OCLS (etype));
397
398 }
399
400 /*-----------------------------------------------------------------*/
401 /* aopForSym - for a true symbol                                   */
402 /*-----------------------------------------------------------------*/
403 static asmop *
404 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
405 {
406   asmop *aop;
407   memmap *space = SPEC_OCLS (sym->etype);
408
409   /* if already has one */
410   if (sym->aop)
411     return sym->aop;
412
413   /* assign depending on the storage class */
414   /* if it is on the stack or indirectly addressable */
415   /* space we need to assign either r0 or r1 to it   */
416   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
417     {
418       sym->aop = aop = newAsmop (0);
419       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
420       aop->size = getSize (sym->type);
421
422       /* now assign the address of the variable to
423          the pointer register */
424       if (aop->type != AOP_STK)
425         {
426
427           if (sym->onStack)
428             {
429               if (_G.accInUse)
430                 emitcode ("push", "acc");
431
432               emitcode ("mov", "a,_bp");
433               emitcode ("add", "a,#0x%02x",
434                         ((sym->stack < 0) ?
435                          ((char) (sym->stack - _G.nRegsSaved)) :
436                          ((char) sym->stack)) & 0xff);
437               emitcode ("mov", "%s,a",
438                         aop->aopu.aop_ptr->name);
439
440               if (_G.accInUse)
441                 emitcode ("pop", "acc");
442             }
443           else
444             emitcode ("mov", "%s,#%s",
445                       aop->aopu.aop_ptr->name,
446                       sym->rname);
447           aop->paged = space->paged;
448         }
449       else
450         aop->aopu.aop_stk = sym->stack;
451       return aop;
452     }
453
454   if (sym->onStack && options.stack10bit)
455     {
456       /* It's on the 10 bit stack, which is located in
457        * far data space.
458        */
459
460       if (_G.accInUse)
461         emitcode ("push", "acc");
462
463       emitcode ("mov", "a,_bp");
464       emitcode ("add", "a,#0x%02x",
465                 ((sym->stack < 0) ?
466                  ((char) (sym->stack - _G.nRegsSaved)) :
467                  ((char) sym->stack)) & 0xff);
468
469       if (useDP2)
470         {
471           if (options.model == MODEL_FLAT24)
472             emitcode ("mov", "dpx1,#0x40");
473           TR_DPTR("#2");
474           emitcode ("mov", "dph1,#0x00");
475           emitcode ("mov", "dpl1, a");
476         }
477       else
478         {
479           if (options.model == MODEL_FLAT24)
480             emitcode ("mov", "dpx,#0x40");
481           emitcode ("mov", "dph,#0x00");
482           emitcode ("mov", "dpl, a");
483         }
484
485       if (_G.accInUse)
486         emitcode ("pop", "acc");
487
488       sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
489       aop->size = getSize (sym->type);
490       return aop;
491     }
492
493   /* if in bit space */
494   if (IN_BITSPACE (space))
495     {
496       sym->aop = aop = newAsmop (AOP_CRY);
497       aop->aopu.aop_dir = sym->rname;
498       aop->size = getSize (sym->type);
499       return aop;
500     }
501   /* if it is in direct space */
502   if (IN_DIRSPACE (space))
503     {
504       sym->aop = aop = newAsmop (AOP_DIR);
505       aop->aopu.aop_dir = sym->rname;
506       aop->size = getSize (sym->type);
507       return aop;
508     }
509
510   /* special case for a function */
511   if (IS_FUNC (sym->type))
512     {
513       sym->aop = aop = newAsmop (AOP_IMMD);
514       aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
515       strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
516       aop->size = FPTRSIZE;
517       return aop;
518     }
519
520   /* only remaining is far space */
521   /* in which case DPTR gets the address */
522   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
523   if (useDP2)
524     {
525       genSetDPTR (1);
526       _flushLazyDPS ();
527       emitcode ("mov", "dptr,#%s", sym->rname);
528       genSetDPTR (0);
529     }
530   else
531     {
532       emitcode ("mov", "dptr,#%s", sym->rname);
533     }
534   aop->size = getSize (sym->type);
535
536   /* if it is in code space */
537   if (IN_CODESPACE (space))
538     aop->code = 1;
539
540   return aop;
541 }
542
543 /*-----------------------------------------------------------------*/
544 /* aopForRemat - rematerialzes an object                           */
545 /*-----------------------------------------------------------------*/
546 static asmop *
547 aopForRemat (symbol * sym)
548 {
549   iCode *ic = sym->rematiCode;
550   asmop *aop = newAsmop (AOP_IMMD);
551   int ptr_type ;
552   int val = 0;
553
554   for (;;)
555     {
556       if (ic->op == '+')
557         val += (int) operandLitValue (IC_RIGHT (ic));
558       else if (ic->op == '-')
559         val -= (int) operandLitValue (IC_RIGHT (ic));
560       else if (IS_CAST_ICODE(ic)) {
561               sym_link *from_type = operandType(IC_RIGHT(ic));
562               aop->aopu.aop_immd.from_cast_remat = 1;
563               ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
564               ptr_type = DCL_TYPE(from_type);
565               continue ;
566       } else break;
567       
568       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
569     }
570
571   if (val)
572     sprintf (buffer, "(%s %c 0x%04x)",
573              OP_SYMBOL (IC_LEFT (ic))->rname,
574              val >= 0 ? '+' : '-',
575              abs (val) & 0xffff);
576   else
577     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
578
579   aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
580   strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
581   /* set immd2 field if required */
582   if (aop->aopu.aop_immd.from_cast_remat) {
583           sprintf(buffer,"#0x%02x",ptr_type);
584           aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
585           strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
586   }
587
588   return aop;
589 }
590
591 /*-----------------------------------------------------------------*/
592 /* regsInCommon - two operands have some registers in common       */
593 /*-----------------------------------------------------------------*/
594 static bool
595 regsInCommon (operand * op1, operand * op2)
596 {
597   symbol *sym1, *sym2;
598   int i;
599
600   /* if they have registers in common */
601   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
602     return FALSE;
603
604   sym1 = OP_SYMBOL (op1);
605   sym2 = OP_SYMBOL (op2);
606
607   if (sym1->nRegs == 0 || sym2->nRegs == 0)
608     return FALSE;
609
610   for (i = 0; i < sym1->nRegs; i++)
611     {
612       int j;
613       if (!sym1->regs[i])
614         continue;
615
616       for (j = 0; j < sym2->nRegs; j++)
617         {
618           if (!sym2->regs[j])
619             continue;
620
621           if (sym2->regs[j] == sym1->regs[i])
622             return TRUE;
623         }
624     }
625
626   return FALSE;
627 }
628
629 /*-----------------------------------------------------------------*/
630 /* operandsEqu - equivalent                                        */
631 /*-----------------------------------------------------------------*/
632 static bool
633 operandsEqu (operand * op1, operand * op2)
634 {
635   symbol *sym1, *sym2;
636
637   /* if they not symbols */
638   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
639     return FALSE;
640
641   sym1 = OP_SYMBOL (op1);
642   sym2 = OP_SYMBOL (op2);
643
644   /* if both are itemps & one is spilt
645      and the other is not then false */
646   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
647       sym1->isspilt != sym2->isspilt)
648     return FALSE;
649
650   /* if they are the same */
651   if (sym1 == sym2)
652     return TRUE;
653
654   if (strcmp (sym1->rname, sym2->rname) == 0)
655     return TRUE;
656
657
658   /* if left is a tmp & right is not */
659   if (IS_ITEMP (op1) &&
660       !IS_ITEMP (op2) &&
661       sym1->isspilt &&
662       (sym1->usl.spillLoc == sym2))
663     return TRUE;
664
665   if (IS_ITEMP (op2) &&
666       !IS_ITEMP (op1) &&
667       sym2->isspilt &&
668       sym1->level > 0 &&
669       (sym2->usl.spillLoc == sym1))
670     return TRUE;
671
672   return FALSE;
673 }
674
675 /*-----------------------------------------------------------------*/
676 /* sameRegs - two asmops have the same registers                   */
677 /*-----------------------------------------------------------------*/
678 static bool
679 sameRegs (asmop * aop1, asmop * aop2)
680 {
681   int i;
682
683   if (aop1 == aop2)
684     {
685       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
686         {
687           return FALSE;
688         }
689       return TRUE;
690     }
691
692   if (aop1->type != AOP_REG ||
693       aop2->type != AOP_REG)
694     return FALSE;
695
696   if (aop1->size != aop2->size)
697     return FALSE;
698
699   for (i = 0; i < aop1->size; i++)
700     if (aop1->aopu.aop_reg[i] !=
701         aop2->aopu.aop_reg[i])
702       return FALSE;
703
704   return TRUE;
705 }
706
707 /*-----------------------------------------------------------------*/
708 /* aopOp - allocates an asmop for an operand  :                    */
709 /*-----------------------------------------------------------------*/
710 static void
711 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
712 {
713   asmop *aop;
714   symbol *sym;
715   int i;
716
717   if (!op)
718     return;
719
720   /* if this a literal */
721   if (IS_OP_LITERAL (op))
722     {
723       op->aop = aop = newAsmop (AOP_LIT);
724       aop->aopu.aop_lit = op->operand.valOperand;
725       aop->size = getSize (operandType (op));
726       return;
727     }
728
729   /* if already has a asmop then continue */
730   if (op->aop)
731     return;
732
733   /* if the underlying symbol has a aop */
734   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
735     {
736       op->aop = OP_SYMBOL (op)->aop;
737       return;
738     }
739
740   /* if this is a true symbol */
741   if (IS_TRUE_SYMOP (op))
742     {
743       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
744       return;
745     }
746
747   /* this is a temporary : this has
748      only four choices :
749      a) register
750      b) spillocation
751      c) rematerialize
752      d) conditional
753      e) can be a return use only */
754
755   sym = OP_SYMBOL (op);
756
757
758   /* if the type is a conditional */
759   if (sym->regType == REG_CND)
760     {
761       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
762       aop->size = 0;
763       return;
764     }
765
766   /* if it is spilt then two situations
767      a) is rematerialize
768      b) has a spill location */
769   if (sym->isspilt || sym->nRegs == 0)
770     {
771
772       /* rematerialize it NOW */
773       if (sym->remat)
774         {
775           sym->aop = op->aop = aop =
776             aopForRemat (sym);
777           aop->size = getSize (sym->type);
778           return;
779         }
780
781       if (sym->accuse)
782         {
783           int i;
784           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
785           aop->size = getSize (sym->type);
786           for (i = 0; i < 2; i++)
787             aop->aopu.aop_str[i] = accUse[i];
788           return;
789         }
790
791       if (sym->ruonly)
792         {
793           int i;
794
795           if (useDP2)
796             {
797               /* a AOP_STR uses DPTR, but DPTR is already in use;
798                * we're just hosed.
799                */
800               fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
801             }
802
803           aop = op->aop = sym->aop = newAsmop (AOP_STR);
804           aop->size = getSize (sym->type);
805           for (i = 0; i < (int) fReturnSizeDS390; i++)
806             aop->aopu.aop_str[i] = fReturn[i];
807           return;
808         }
809
810       /* else spill location  */
811       sym->aop = op->aop = aop =
812         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
813       aop->size = getSize (sym->type);
814       return;
815     }
816
817   /* must be in a register */
818   sym->aop = op->aop = aop = newAsmop (AOP_REG);
819   aop->size = sym->nRegs;
820   for (i = 0; i < sym->nRegs; i++)
821     aop->aopu.aop_reg[i] = sym->regs[i];
822 }
823
824 /*-----------------------------------------------------------------*/
825 /* freeAsmop - free up the asmop given to an operand               */
826 /*----------------------------------------------------------------*/
827 static void
828 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
829 {
830   asmop *aop;
831
832   if (!op)
833     aop = aaop;
834   else
835     aop = op->aop;
836
837   if (!aop)
838     return;
839
840   if (aop->freed)
841     goto dealloc;
842
843   aop->freed = 1;
844
845   /* depending on the asmop type only three cases need work AOP_RO
846      , AOP_R1 && AOP_STK */
847   switch (aop->type)
848     {
849     case AOP_R0:
850       if (_G.r0Pushed)
851         {
852           if (pop)
853             {
854               emitcode ("pop", "ar0");
855               _G.r0Pushed--;
856             }
857         }
858       bitVectUnSetBit (ic->rUsed, R0_IDX);
859       break;
860
861     case AOP_R1:
862       if (_G.r1Pushed)
863         {
864           if (pop)
865             {
866               emitcode ("pop", "ar1");
867               _G.r1Pushed--;
868             }
869         }
870       bitVectUnSetBit (ic->rUsed, R1_IDX);
871       break;
872
873     case AOP_STK:
874       {
875         int sz = aop->size;
876         int stk = aop->aopu.aop_stk + aop->size;
877         bitVectUnSetBit (ic->rUsed, R0_IDX);
878         bitVectUnSetBit (ic->rUsed, R1_IDX);
879
880         getFreePtr (ic, &aop, FALSE);
881
882         if (options.stack10bit)
883           {
884             /* I'm not sure what to do here yet... */
885             /* #STUB */
886             fprintf (stderr,
887                      "*** Warning: probably generating bad code for "
888                      "10 bit stack mode.\n");
889           }
890
891         if (stk)
892           {
893             emitcode ("mov", "a,_bp");
894             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
895             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
896           }
897         else
898           {
899             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
900           }
901
902         while (sz--)
903           {
904             emitcode ("pop", "acc");
905             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
906             if (!sz)
907               break;
908             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
909           }
910         op->aop = aop;
911         freeAsmop (op, NULL, ic, TRUE);
912         if (_G.r0Pushed)
913           {
914             emitcode ("pop", "ar0");
915             _G.r0Pushed--;
916           }
917
918         if (_G.r1Pushed)
919           {
920             emitcode ("pop", "ar1");
921             _G.r1Pushed--;
922           }
923       }
924     }
925
926 dealloc:
927   /* all other cases just dealloc */
928   if (op)
929     {
930       op->aop = NULL;
931       if (IS_SYMOP (op))
932         {
933           OP_SYMBOL (op)->aop = NULL;
934           /* if the symbol has a spill */
935           if (SPIL_LOC (op))
936             SPIL_LOC (op)->aop = NULL;
937         }
938     }
939 }
940
941 /*------------------------------------------------------------------*/
942 /* aopGet - for fetching value of the aop                           */
943 /*                    */
944 /* Set canClobberACC if you are sure it is OK to clobber the value  */
945 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
946 /* just less efficient.               */
947 /*------------------------------------------------------------------*/
948
949 static char *
950 aopGet (asmop * aop,
951         int offset,
952         bool bit16,
953         bool dname,
954         bool canClobberACC)
955 {
956   char *s = buffer;
957   char *rs;
958
959   /* offset is greater than
960      size then zero */
961   if (offset > (aop->size - 1) &&
962       aop->type != AOP_LIT)
963     return zero;
964
965   /* depending on type */
966   switch (aop->type)
967     {
968
969     case AOP_R0:
970     case AOP_R1:
971       /* if we need to increment it */
972       while (offset > aop->coff)
973         {
974           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
975           aop->coff++;
976         }
977
978       while (offset < aop->coff)
979         {
980           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
981           aop->coff--;
982         }
983
984       aop->coff = offset;
985       if (aop->paged)
986         {
987           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
988           return (dname ? "acc" : "a");
989         }
990       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
991       rs = Safe_calloc (1, strlen (s) + 1);
992       strcpy (rs, s);
993       return rs;
994
995     case AOP_DPTR:
996     case AOP_DPTR2:
997
998       if (aop->type == AOP_DPTR2)
999         {
1000           genSetDPTR (1);
1001           if (!canClobberACC)
1002             {
1003                     TR_AP("#1");
1004                     emitcode ("xch", "a, %s", DP2_RESULT_REG);
1005             }
1006         }
1007
1008       _flushLazyDPS ();
1009
1010       while (offset > aop->coff)
1011         {
1012           emitcode ("inc", "dptr");
1013           aop->coff++;
1014         }
1015
1016       while (offset < aop->coff)
1017         {
1018           emitcode ("lcall", "__decdptr");
1019           aop->coff--;
1020         }
1021
1022       aop->coff = offset;
1023       if (aop->code)
1024         {
1025           emitcode ("clr", "a");
1026           emitcode ("movc", "a,@a+dptr");
1027         }
1028       else
1029         {
1030           emitcode ("movx", "a,@dptr");
1031         }
1032
1033       if (aop->type == AOP_DPTR2)
1034         {
1035           genSetDPTR (0);
1036           if (!canClobberACC)
1037             {
1038        TR_AP("#2");
1039               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1040               return DP2_RESULT_REG;
1041             }
1042         }
1043       return (dname ? "acc" : "a");
1044
1045     case AOP_IMMD:
1046       if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1047               sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1048       } else if (bit16)
1049         sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1050       else if (offset)
1051         sprintf (s, "#(%s >> %d)",
1052                  aop->aopu.aop_immd.aop_immd1,
1053                  offset * 8);
1054       else
1055         sprintf (s, "#%s",
1056                  aop->aopu.aop_immd.aop_immd1);
1057       rs = Safe_calloc (1, strlen (s) + 1);
1058       strcpy (rs, s);
1059       return rs;
1060
1061     case AOP_DIR:
1062       if (offset)
1063         sprintf (s, "(%s + %d)",
1064                  aop->aopu.aop_dir,
1065                  offset);
1066       else
1067         sprintf (s, "%s", aop->aopu.aop_dir);
1068       rs = Safe_calloc (1, strlen (s) + 1);
1069       strcpy (rs, s);
1070       return rs;
1071
1072     case AOP_REG:
1073       if (dname)
1074         return aop->aopu.aop_reg[offset]->dname;
1075       else
1076         return aop->aopu.aop_reg[offset]->name;
1077
1078     case AOP_CRY:
1079       emitcode ("clr", "a");
1080       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1081       emitcode ("rlc", "a");
1082       return (dname ? "acc" : "a");
1083
1084     case AOP_ACC:
1085       if (!offset && dname)
1086         return "acc";
1087       return aop->aopu.aop_str[offset];
1088
1089     case AOP_LIT:
1090       return aopLiteral (aop->aopu.aop_lit, offset);
1091
1092     case AOP_STR:
1093       aop->coff = offset;
1094       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1095           dname)
1096         return "acc";
1097
1098       return aop->aopu.aop_str[offset];
1099
1100     }
1101
1102   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1103           "aopget got unsupported aop->type");
1104   exit (1);
1105 }
1106 /*-----------------------------------------------------------------*/
1107 /* aopPut - puts a string for a aop                                */
1108 /*-----------------------------------------------------------------*/
1109 static void
1110 aopPut (asmop * aop, char *s, int offset)
1111 {
1112   char *d = buffer;
1113
1114   if (aop->size && offset > (aop->size - 1))
1115     {
1116       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1117               "aopPut got offset > aop->size");
1118       exit (1);
1119     }
1120
1121   /* will assign value to value */
1122   /* depending on where it is ofcourse */
1123   switch (aop->type)
1124     {
1125     case AOP_DIR:
1126       if (offset)
1127         sprintf (d, "(%s + %d)",
1128                  aop->aopu.aop_dir, offset);
1129       else
1130         sprintf (d, "%s", aop->aopu.aop_dir);
1131
1132       if (strcmp (d, s))
1133         emitcode ("mov", "%s,%s", d, s);
1134
1135       break;
1136
1137     case AOP_REG:
1138       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1139           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1140         {
1141           if (*s == '@' ||
1142               strcmp (s, "r0") == 0 ||
1143               strcmp (s, "r1") == 0 ||
1144               strcmp (s, "r2") == 0 ||
1145               strcmp (s, "r3") == 0 ||
1146               strcmp (s, "r4") == 0 ||
1147               strcmp (s, "r5") == 0 ||
1148               strcmp (s, "r6") == 0 ||
1149               strcmp (s, "r7") == 0)
1150             emitcode ("mov", "%s,%s",
1151                       aop->aopu.aop_reg[offset]->dname, s);
1152           else
1153             emitcode ("mov", "%s,%s",
1154                       aop->aopu.aop_reg[offset]->name, s);
1155         }
1156       break;
1157
1158     case AOP_DPTR:
1159     case AOP_DPTR2:
1160
1161       if (aop->type == AOP_DPTR2)
1162         {
1163           genSetDPTR (1);
1164         }
1165       _flushLazyDPS ();
1166
1167       if (aop->code)
1168         {
1169           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1170                   "aopPut writting to code space");
1171           exit (1);
1172         }
1173
1174       while (offset > aop->coff)
1175         {
1176           aop->coff++;
1177           emitcode ("inc", "dptr");
1178         }
1179
1180       while (offset < aop->coff)
1181         {
1182           aop->coff--;
1183           emitcode ("lcall", "__decdptr");
1184         }
1185
1186       aop->coff = offset;
1187
1188       /* if not in accumulater */
1189       MOVA (s);
1190
1191       emitcode ("movx", "@dptr,a");
1192
1193       if (aop->type == AOP_DPTR2)
1194         {
1195           genSetDPTR (0);
1196         }
1197       break;
1198
1199     case AOP_R0:
1200     case AOP_R1:
1201       while (offset > aop->coff)
1202         {
1203           aop->coff++;
1204           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1205         }
1206       while (offset < aop->coff)
1207         {
1208           aop->coff--;
1209           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1210         }
1211       aop->coff = offset;
1212
1213       if (aop->paged)
1214         {
1215           MOVA (s);
1216           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1217
1218         }
1219       else if (*s == '@')
1220         {
1221           MOVA (s);
1222           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1223         }
1224       else if (strcmp (s, "r0") == 0 ||
1225                strcmp (s, "r1") == 0 ||
1226                strcmp (s, "r2") == 0 ||
1227                strcmp (s, "r3") == 0 ||
1228                strcmp (s, "r4") == 0 ||
1229                strcmp (s, "r5") == 0 ||
1230                strcmp (s, "r6") == 0 ||
1231                strcmp (s, "r7") == 0)
1232         {
1233           char buffer[10];
1234           sprintf (buffer, "a%s", s);
1235           emitcode ("mov", "@%s,%s",
1236                     aop->aopu.aop_ptr->name, buffer);
1237         }
1238       else
1239         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1240
1241       break;
1242
1243     case AOP_STK:
1244       if (strcmp (s, "a") == 0)
1245         emitcode ("push", "acc");
1246       else
1247         if (*s=='@') {
1248           MOVA(s);
1249           emitcode ("push", "acc");
1250         } else {
1251           emitcode ("push", s);
1252         }
1253
1254       break;
1255
1256     case AOP_CRY:
1257       /* if bit variable */
1258       if (!aop->aopu.aop_dir)
1259         {
1260           emitcode ("clr", "a");
1261           emitcode ("rlc", "a");
1262         }
1263       else
1264         {
1265           if (s == zero)
1266             emitcode ("clr", "%s", aop->aopu.aop_dir);
1267           else if (s == one)
1268             emitcode ("setb", "%s", aop->aopu.aop_dir);
1269           else if (!strcmp (s, "c"))
1270             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1271           else
1272             {
1273               if (strcmp (s, "a"))
1274                 {
1275                   MOVA (s);
1276                 }
1277               {
1278                 symbol *lbl = newiTempLabel (NULL);
1279                 emitcode ("clr", "c");
1280                 emitcode ("jz", "%05d$", lbl->key + 100);
1281                 emitcode ("cpl", "c");
1282                 emitcode ("", "%05d$:", lbl->key + 100);
1283                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1284               }
1285             }
1286         }
1287       break;
1288
1289     case AOP_STR:
1290       aop->coff = offset;
1291       if (strcmp (aop->aopu.aop_str[offset], s))
1292         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1293       break;
1294
1295     case AOP_ACC:
1296       aop->coff = offset;
1297       if (!offset && (strcmp (s, "acc") == 0))
1298         break;
1299
1300       if (strcmp (aop->aopu.aop_str[offset], s))
1301         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1302       break;
1303
1304     default:
1305       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1306               "aopPut got unsupported aop->type");
1307       exit (1);
1308     }
1309
1310 }
1311
1312
1313 /*--------------------------------------------------------------------*/
1314 /* reAdjustPreg - points a register back to where it should (coff==0) */
1315 /*--------------------------------------------------------------------*/
1316 static void
1317 reAdjustPreg (asmop * aop)
1318 {
1319   if ((aop->coff==0) || (aop->size <= 1)) {
1320     return;
1321   }
1322
1323   switch (aop->type)
1324     {
1325     case AOP_R0:
1326     case AOP_R1:
1327       while (aop->coff--)
1328         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1329       break;
1330     case AOP_DPTR:
1331     case AOP_DPTR2:
1332       if (aop->type == AOP_DPTR2)
1333         {
1334           genSetDPTR (1);
1335           _flushLazyDPS ();
1336         }
1337       while (aop->coff--)
1338         {
1339           emitcode ("lcall", "__decdptr");
1340         }
1341
1342       if (aop->type == AOP_DPTR2)
1343         {
1344           genSetDPTR (0);
1345         }
1346       break;
1347
1348     }
1349   aop->coff=0;
1350 }
1351
1352 #define AOP(op) op->aop
1353 #define AOP_TYPE(op) AOP(op)->type
1354 #define AOP_SIZE(op) AOP(op)->size
1355 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1356                        AOP_TYPE(x) == AOP_R0))
1357
1358 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1359                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1360                          AOP(x)->paged))
1361
1362 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1363                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1364                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1365
1366 /* Workaround for DS80C390 bug: div ab may return bogus results
1367  * if A is accessed in instruction immediately before the div.
1368  *
1369  * Will be fixed in B4 rev of processor, Dallas claims.
1370  */
1371
1372 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1373     if (!AOP_NEEDSACC(RIGHT))         \
1374     {               \
1375       /* We can load A first, then B, since     \
1376        * B (the RIGHT operand) won't clobber A,   \
1377        * thus avoiding touching A right before the div. \
1378        */             \
1379       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1380       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1381       MOVA(L);            \
1382       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1383     }               \
1384     else              \
1385     {               \
1386       /* Just stuff in a nop after loading A. */    \
1387       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1388       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1389       MOVA(L);            \
1390       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1391     }
1392
1393 /*-----------------------------------------------------------------*/
1394 /* genNotFloat - generates not for float operations              */
1395 /*-----------------------------------------------------------------*/
1396 static void
1397 genNotFloat (operand * op, operand * res)
1398 {
1399   int size, offset;
1400   char *l;
1401   symbol *tlbl;
1402
1403   D (emitcode (";", "genNotFloat ");
1404     );
1405
1406   /* we will put 127 in the first byte of
1407      the result */
1408   aopPut (AOP (res), "#127", 0);
1409   size = AOP_SIZE (op) - 1;
1410   offset = 1;
1411
1412   _startLazyDPSEvaluation ();
1413   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1414   MOVA (l);
1415
1416   while (size--)
1417     {
1418       emitcode ("orl", "a,%s",
1419                 aopGet (op->aop,
1420                         offset++, FALSE, FALSE, FALSE));
1421     }
1422   _endLazyDPSEvaluation ();
1423
1424   tlbl = newiTempLabel (NULL);
1425   aopPut (res->aop, one, 1);
1426   emitcode ("jz", "%05d$", (tlbl->key + 100));
1427   aopPut (res->aop, zero, 1);
1428   emitcode ("", "%05d$:", (tlbl->key + 100));
1429
1430   size = res->aop->size - 2;
1431   offset = 2;
1432   /* put zeros in the rest */
1433   while (size--)
1434     aopPut (res->aop, zero, offset++);
1435 }
1436
1437 /*-----------------------------------------------------------------*/
1438 /* opIsGptr: returns non-zero if the passed operand is       */
1439 /* a generic pointer type.             */
1440 /*-----------------------------------------------------------------*/
1441 static int
1442 opIsGptr (operand * op)
1443 {
1444   sym_link *type = operandType (op);
1445
1446   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1447     {
1448       return 1;
1449     }
1450   return 0;
1451 }
1452
1453 /*-----------------------------------------------------------------*/
1454 /* getDataSize - get the operand data size                         */
1455 /*-----------------------------------------------------------------*/
1456 static int
1457 getDataSize (operand * op)
1458 {
1459   int size;
1460   size = AOP_SIZE (op);
1461   if (size == GPTRSIZE)
1462     {
1463       sym_link *type = operandType (op);
1464       if (IS_GENPTR (type))
1465         {
1466           /* generic pointer; arithmetic operations
1467            * should ignore the high byte (pointer type).
1468            */
1469           size--;
1470         }
1471     }
1472   return size;
1473 }
1474
1475 /*-----------------------------------------------------------------*/
1476 /* outAcc - output Acc                                             */
1477 /*-----------------------------------------------------------------*/
1478 static void
1479 outAcc (operand * result)
1480 {
1481   int size, offset;
1482   size = getDataSize (result);
1483   if (size)
1484     {
1485       aopPut (AOP (result), "a", 0);
1486       size--;
1487       offset = 1;
1488       /* unsigned or positive */
1489       while (size--)
1490         {
1491           aopPut (AOP (result), zero, offset++);
1492         }
1493     }
1494 }
1495
1496 /*-----------------------------------------------------------------*/
1497 /* outBitC - output a bit C                                        */
1498 /*-----------------------------------------------------------------*/
1499 static void
1500 outBitC (operand * result)
1501 {
1502   /* if the result is bit */
1503   if (AOP_TYPE (result) == AOP_CRY)
1504     {
1505       aopPut (AOP (result), "c", 0);
1506     }
1507   else
1508     {
1509       emitcode ("clr", "a");
1510       emitcode ("rlc", "a");
1511       outAcc (result);
1512     }
1513 }
1514
1515 /*-----------------------------------------------------------------*/
1516 /* toBoolean - emit code for orl a,operator(sizeop)                */
1517 /*-----------------------------------------------------------------*/
1518 static void
1519 toBoolean (operand * oper)
1520 {
1521   int   size = AOP_SIZE (oper) - 1;
1522   int   offset = 1;
1523   bool usedB = FALSE;
1524
1525   /* The generic part of a generic pointer should
1526    * not participate in it's truth value.
1527    *
1528    * i.e. 0x10000000 is zero.
1529    */
1530   if (opIsGptr (oper))
1531     {
1532       D (emitcode (";", "toBoolean: generic ptr special case.");
1533         );
1534       size--;
1535     }
1536
1537   _startLazyDPSEvaluation ();
1538   if (AOP_NEEDSACC (oper) && size)
1539     {
1540       usedB = TRUE;
1541       emitcode ("push", "b");
1542       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1543     }
1544   else
1545     {
1546       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1547     }
1548   while (size--)
1549     {
1550       if (usedB)
1551         {
1552           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1553         }
1554       else
1555         {
1556           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1557         }
1558     }
1559   _endLazyDPSEvaluation ();
1560
1561   if (usedB)
1562     {
1563       emitcode ("mov", "a,b");
1564       emitcode ("pop", "b");
1565     }
1566 }
1567
1568
1569 /*-----------------------------------------------------------------*/
1570 /* genNot - generate code for ! operation                          */
1571 /*-----------------------------------------------------------------*/
1572 static void
1573 genNot (iCode * ic)
1574 {
1575   symbol *tlbl;
1576   sym_link *optype = operandType (IC_LEFT (ic));
1577
1578   D (emitcode (";", "genNot ");
1579     );
1580
1581   /* assign asmOps to operand & result */
1582   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1583   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1584
1585   /* if in bit space then a special case */
1586   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1587     {
1588       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1589       emitcode ("cpl", "c");
1590       outBitC (IC_RESULT (ic));
1591       goto release;
1592     }
1593
1594   /* if type float then do float */
1595   if (IS_FLOAT (optype))
1596     {
1597       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1598       goto release;
1599     }
1600
1601   toBoolean (IC_LEFT (ic));
1602
1603   tlbl = newiTempLabel (NULL);
1604   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1605   emitcode ("", "%05d$:", tlbl->key + 100);
1606   outBitC (IC_RESULT (ic));
1607
1608 release:
1609   /* release the aops */
1610   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1611   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1612 }
1613
1614
1615 /*-----------------------------------------------------------------*/
1616 /* genCpl - generate code for complement                           */
1617 /*-----------------------------------------------------------------*/
1618 static void
1619 genCpl (iCode * ic)
1620 {
1621   int offset = 0;
1622   int size;
1623
1624   D (emitcode (";", "genCpl ");
1625     );
1626
1627
1628   /* assign asmOps to operand & result */
1629   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1630   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1631
1632   /* if both are in bit space then
1633      a special case */
1634   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1635       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1636     {
1637
1638       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1639       emitcode ("cpl", "c");
1640       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1641       goto release;
1642     }
1643
1644   size = AOP_SIZE (IC_RESULT (ic));
1645   _startLazyDPSEvaluation ();
1646   while (size--)
1647     {
1648       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1649       MOVA (l);
1650       emitcode ("cpl", "a");
1651       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1652     }
1653   _endLazyDPSEvaluation ();
1654
1655
1656 release:
1657   /* release the aops */
1658   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1659   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1660 }
1661
1662 /*-----------------------------------------------------------------*/
1663 /* genUminusFloat - unary minus for floating points                */
1664 /*-----------------------------------------------------------------*/
1665 static void
1666 genUminusFloat (operand * op, operand * result)
1667 {
1668   int size, offset = 0;
1669   char *l;
1670   /* for this we just need to flip the
1671      first it then copy the rest in place */
1672   D (emitcode (";", "genUminusFloat");
1673     );
1674
1675   _startLazyDPSEvaluation ();
1676   size = AOP_SIZE (op) - 1;
1677   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1678   MOVA (l);
1679
1680   emitcode ("cpl", "acc.7");
1681   aopPut (AOP (result), "a", 3);
1682
1683   while (size--)
1684     {
1685       aopPut (AOP (result),
1686               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1687               offset);
1688       offset++;
1689     }
1690   _endLazyDPSEvaluation ();
1691 }
1692
1693 /*-----------------------------------------------------------------*/
1694 /* genUminus - unary minus code generation                         */
1695 /*-----------------------------------------------------------------*/
1696 static void
1697 genUminus (iCode * ic)
1698 {
1699   int offset, size;
1700   sym_link *optype, *rtype;
1701
1702   D (emitcode (";", "genUminus ");
1703     );
1704
1705
1706   /* assign asmops */
1707   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1708   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1709
1710   /* if both in bit space then special
1711      case */
1712   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1713       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1714     {
1715
1716       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1717       emitcode ("cpl", "c");
1718       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1719       goto release;
1720     }
1721
1722   optype = operandType (IC_LEFT (ic));
1723   rtype = operandType (IC_RESULT (ic));
1724
1725   /* if float then do float stuff */
1726   if (IS_FLOAT (optype))
1727     {
1728       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1729       goto release;
1730     }
1731
1732   /* otherwise subtract from zero */
1733   size = AOP_SIZE (IC_LEFT (ic));
1734   offset = 0;
1735   _startLazyDPSEvaluation ();
1736   while (size--)
1737     {
1738       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1739       if (!strcmp (l, "a"))
1740         {
1741           if (offset == 0)
1742             SETC;
1743           emitcode ("cpl", "a");
1744           emitcode ("addc", "a,#0");
1745         }
1746       else
1747         {
1748           if (offset == 0)
1749             CLRC;
1750           emitcode ("clr", "a");
1751           emitcode ("subb", "a,%s", l);
1752         }
1753       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1754     }
1755   _endLazyDPSEvaluation ();
1756
1757   /* if any remaining bytes in the result */
1758   /* we just need to propagate the sign   */
1759   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1760     {
1761       emitcode ("rlc", "a");
1762       emitcode ("subb", "a,acc");
1763       while (size--)
1764         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1765     }
1766
1767 release:
1768   /* release the aops */
1769   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1770   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1771 }
1772
1773 /*-----------------------------------------------------------------*/
1774 /* saveRegisters - will look for a call and save the registers     */
1775 /*-----------------------------------------------------------------*/
1776 static void
1777 saveRegisters (iCode * lic)
1778 {
1779   int i;
1780   iCode *ic;
1781   bitVect *rsave;
1782   sym_link *detype;
1783
1784   /* look for call */
1785   for (ic = lic; ic; ic = ic->next)
1786     if (ic->op == CALL || ic->op == PCALL)
1787       break;
1788
1789   if (!ic)
1790     {
1791       fprintf (stderr, "found parameter push with no function call\n");
1792       return;
1793     }
1794
1795   /* if the registers have been saved already then
1796      do nothing */
1797   if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1798       IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1799     return;
1800
1801   /* find the registers in use at this time
1802      and push them away to safety */
1803   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1804                          ic->rUsed);
1805
1806   ic->regsSaved = 1;
1807   if (options.useXstack)
1808     {
1809       if (bitVectBitValue (rsave, R0_IDX))
1810         emitcode ("mov", "b,r0");
1811       emitcode ("mov", "r0,%s", spname);
1812       for (i = 0; i < ds390_nRegs; i++)
1813         {
1814           if (bitVectBitValue (rsave, i))
1815             {
1816               if (i == R0_IDX)
1817                 emitcode ("mov", "a,b");
1818               else
1819                 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1820               emitcode ("movx", "@r0,a");
1821               emitcode ("inc", "r0");
1822             }
1823         }
1824       emitcode ("mov", "%s,r0", spname);
1825       if (bitVectBitValue (rsave, R0_IDX))
1826         emitcode ("mov", "r0,b");
1827     }
1828   else
1829     for (i = 0; i < ds390_nRegs; i++)
1830       {
1831         if (bitVectBitValue (rsave, i))
1832           emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1833       }
1834
1835   detype = getSpec (operandType (IC_LEFT (ic)));
1836 }
1837
1838 /*-----------------------------------------------------------------*/
1839 /* unsaveRegisters - pop the pushed registers                      */
1840 /*-----------------------------------------------------------------*/
1841 static void
1842 unsaveRegisters (iCode * ic)
1843 {
1844   int i;
1845   bitVect *rsave;
1846   /* find the registers in use at this time
1847      and push them away to safety */
1848   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1849                          ic->rUsed);
1850
1851   if (options.useXstack)
1852     {
1853       emitcode ("mov", "r0,%s", spname);
1854       for (i = ds390_nRegs; i >= 0; i--)
1855         {
1856           if (bitVectBitValue (rsave, i))
1857             {
1858               emitcode ("dec", "r0");
1859               emitcode ("movx", "a,@r0");
1860               if (i == R0_IDX)
1861                 emitcode ("mov", "b,a");
1862               else
1863                 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1864             }
1865
1866         }
1867       emitcode ("mov", "%s,r0", spname);
1868       if (bitVectBitValue (rsave, R0_IDX))
1869         emitcode ("mov", "r0,b");
1870     }
1871   else
1872     for (i = ds390_nRegs; i >= 0; i--)
1873       {
1874         if (bitVectBitValue (rsave, i))
1875           emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1876       }
1877
1878 }
1879
1880
1881 /*-----------------------------------------------------------------*/
1882 /* pushSide -                */
1883 /*-----------------------------------------------------------------*/
1884 static void
1885 pushSide (operand * oper, int size)
1886 {
1887   int offset = 0;
1888   _startLazyDPSEvaluation ();
1889   while (size--)
1890     {
1891       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1892       if (AOP_TYPE (oper) != AOP_REG &&
1893           AOP_TYPE (oper) != AOP_DIR &&
1894           strcmp (l, "a"))
1895         {
1896           emitcode ("mov", "a,%s", l);
1897           emitcode ("push", "acc");
1898         }
1899       else
1900         emitcode ("push", "%s", l);
1901     }
1902   _endLazyDPSEvaluation ();
1903 }
1904
1905 /*-----------------------------------------------------------------*/
1906 /* assignResultValue -               */
1907 /*-----------------------------------------------------------------*/
1908 static void
1909 assignResultValue (operand * oper)
1910 {
1911   int offset = 0;
1912   int size = AOP_SIZE (oper);
1913
1914   _startLazyDPSEvaluation ();
1915   while (size--)
1916     {
1917       aopPut (AOP (oper), fReturn[offset], offset);
1918       offset++;
1919     }
1920   _endLazyDPSEvaluation ();
1921 }
1922
1923
1924 /*-----------------------------------------------------------------*/
1925 /* genXpush - pushes onto the external stack                       */
1926 /*-----------------------------------------------------------------*/
1927 static void
1928 genXpush (iCode * ic)
1929 {
1930   asmop *aop = newAsmop (0);
1931   regs *r;
1932   int size, offset = 0;
1933
1934   D (emitcode (";", "genXpush ");
1935     );
1936
1937   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1938   r = getFreePtr (ic, &aop, FALSE);
1939
1940
1941   emitcode ("mov", "%s,_spx", r->name);
1942
1943   size = AOP_SIZE (IC_LEFT (ic));
1944   _startLazyDPSEvaluation ();
1945   while (size--)
1946     {
1947
1948       char *l = aopGet (AOP (IC_LEFT (ic)),
1949                         offset++, FALSE, FALSE, TRUE);
1950       MOVA (l);
1951       emitcode ("movx", "@%s,a", r->name);
1952       emitcode ("inc", "%s", r->name);
1953
1954     }
1955   _endLazyDPSEvaluation ();
1956
1957
1958   emitcode ("mov", "_spx,%s", r->name);
1959
1960   freeAsmop (NULL, aop, ic, TRUE);
1961   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1962 }
1963
1964 /*-----------------------------------------------------------------*/
1965 /* genIpush - genrate code for pushing this gets a little complex  */
1966 /*-----------------------------------------------------------------*/
1967 static void
1968 genIpush (iCode * ic)
1969 {
1970   int size, offset = 0;
1971   char *l;
1972
1973   D (emitcode (";", "genIpush ");
1974     );
1975
1976   /* if this is not a parm push : ie. it is spill push
1977      and spill push is always done on the local stack */
1978   if (!ic->parmPush)
1979     {
1980
1981       /* and the item is spilt then do nothing */
1982       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1983         return;
1984
1985       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1986       size = AOP_SIZE (IC_LEFT (ic));
1987       /* push it on the stack */
1988       _startLazyDPSEvaluation ();
1989       while (size--)
1990         {
1991           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1992           if (*l == '#')
1993             {
1994               MOVA (l);
1995               l = "acc";
1996             }
1997           emitcode ("push", "%s", l);
1998         }
1999       _endLazyDPSEvaluation ();
2000       return;
2001     }
2002
2003   /* this is a paramter push: in this case we call
2004      the routine to find the call and save those
2005      registers that need to be saved */
2006   saveRegisters (ic);
2007
2008   /* if use external stack then call the external
2009      stack pushing routine */
2010   if (options.useXstack)
2011     {
2012       genXpush (ic);
2013       return;
2014     }
2015
2016   /* then do the push */
2017   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2018
2019   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2020   size = AOP_SIZE (IC_LEFT (ic));
2021
2022   _startLazyDPSEvaluation ();
2023   while (size--)
2024     {
2025       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2026       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2027           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2028           strcmp (l, "a"))
2029         {
2030           emitcode ("mov", "a,%s", l);
2031           emitcode ("push", "acc");
2032         }
2033       else
2034         emitcode ("push", "%s", l);
2035     }
2036   _endLazyDPSEvaluation ();
2037
2038   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2039 }
2040
2041 /*-----------------------------------------------------------------*/
2042 /* genIpop - recover the registers: can happen only for spilling   */
2043 /*-----------------------------------------------------------------*/
2044 static void
2045 genIpop (iCode * ic)
2046 {
2047   int size, offset;
2048
2049   D (emitcode (";", "genIpop ");
2050     );
2051
2052
2053   /* if the temp was not pushed then */
2054   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2055     return;
2056
2057   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2058   size = AOP_SIZE (IC_LEFT (ic));
2059   offset = (size - 1);
2060   _startLazyDPSEvaluation ();
2061   while (size--)
2062     {
2063       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2064                                      FALSE, TRUE, TRUE));
2065     }
2066   _endLazyDPSEvaluation ();
2067
2068   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2069 }
2070
2071 /*-----------------------------------------------------------------*/
2072 /* unsaveRBank - restores the resgister bank from stack            */
2073 /*-----------------------------------------------------------------*/
2074 static void
2075 unsaveRBank (int bank, iCode * ic, bool popPsw)
2076 {
2077   int i;
2078   asmop *aop = NULL;
2079   regs *r = NULL;
2080
2081   if (options.useXstack)
2082   {
2083       if (!ic)
2084       {
2085           /* Assume r0 is available for use. */
2086           r = ds390_regWithIdx (R0_IDX);;          
2087       } 
2088       else
2089       {
2090           aop = newAsmop (0);
2091           r = getFreePtr (ic, &aop, FALSE);
2092       }
2093       emitcode ("mov", "%s,_spx", r->name);      
2094   }
2095   
2096   if (popPsw)
2097     {
2098       if (options.useXstack)
2099       {
2100           emitcode ("movx", "a,@%s", r->name);
2101           emitcode ("mov", "psw,a");
2102           emitcode ("dec", "%s", r->name);
2103         }
2104       else
2105       {
2106         emitcode ("pop", "psw");
2107       }
2108     }
2109
2110   for (i = (ds390_nRegs - 1); i >= 0; i--)
2111     {
2112       if (options.useXstack)
2113         {
2114           emitcode ("movx", "a,@%s", r->name);
2115           emitcode ("mov", "(%s+%d),a",
2116                     regs390[i].base, 8 * bank + regs390[i].offset);
2117           emitcode ("dec", "%s", r->name);
2118
2119         }
2120       else
2121         emitcode ("pop", "(%s+%d)",
2122                   regs390[i].base, 8 * bank + regs390[i].offset);
2123     }
2124
2125   if (options.useXstack)
2126     {
2127       emitcode ("mov", "_spx,%s", r->name);
2128     }
2129     
2130   if (aop)
2131   {
2132       freeAsmop (NULL, aop, ic, TRUE);  
2133   }    
2134 }
2135
2136 /*-----------------------------------------------------------------*/
2137 /* saveRBank - saves an entire register bank on the stack          */
2138 /*-----------------------------------------------------------------*/
2139 static void
2140 saveRBank (int bank, iCode * ic, bool pushPsw)
2141 {
2142   int i;
2143   asmop *aop = NULL;
2144   regs *r = NULL;
2145
2146   if (options.useXstack)
2147     {
2148         if (!ic)
2149         {
2150           /* Assume r0 is available for use. */
2151                   r = ds390_regWithIdx (R0_IDX);;
2152         }
2153         else
2154         {
2155           aop = newAsmop (0);
2156           r = getFreePtr (ic, &aop, FALSE);
2157         }
2158         emitcode ("mov", "%s,_spx", r->name);    
2159     }
2160
2161   for (i = 0; i < ds390_nRegs; i++)
2162     {
2163       if (options.useXstack)
2164         {
2165           emitcode ("inc", "%s", r->name);
2166           emitcode ("mov", "a,(%s+%d)",
2167                     regs390[i].base, 8 * bank + regs390[i].offset);
2168           emitcode ("movx", "@%s,a", r->name);
2169         }
2170       else
2171         emitcode ("push", "(%s+%d)",
2172                   regs390[i].base, 8 * bank + regs390[i].offset);
2173     }
2174
2175   if (pushPsw)
2176     {
2177       if (options.useXstack)
2178         {
2179           emitcode ("mov", "a,psw");
2180           emitcode ("movx", "@%s,a", r->name);
2181           emitcode ("inc", "%s", r->name);
2182           emitcode ("mov", "_spx,%s", r->name);
2183         }
2184       else
2185       {
2186         emitcode ("push", "psw");
2187       }
2188
2189       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2190     }
2191   
2192   if (aop)
2193   {
2194        freeAsmop (NULL, aop, ic, TRUE);
2195   }    
2196     
2197   if (ic)
2198   {  
2199       ic->bankSaved = 1;
2200   }
2201 }
2202
2203 /*-----------------------------------------------------------------*/
2204 /* genCall - generates a call statement                            */
2205 /*-----------------------------------------------------------------*/
2206 static void
2207 genCall (iCode * ic)
2208 {
2209   sym_link *dtype;
2210   bool restoreBank = FALSE;
2211   bool swapBanks = FALSE;
2212
2213   D (emitcode (";", "genCall "););
2214
2215   /* if we are calling a not _naked function that is not using
2216      the same register bank then we need to save the
2217      destination registers on the stack */
2218   dtype = operandType (IC_LEFT (ic));
2219   if (dtype && !IFFUNC_ISNAKED(dtype) &&
2220       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2221       IFFUNC_ISISR (currFunc->type))
2222   {
2223       if (!ic->bankSaved) 
2224       {
2225            /* This is unexpected; the bank should have been saved in
2226             * genFunction.
2227             */
2228            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2229            restoreBank = TRUE;
2230       }
2231       swapBanks = TRUE;
2232   }
2233   
2234     /* if caller saves & we have not saved then */
2235     if (!ic->regsSaved)
2236       saveRegisters (ic);
2237   
2238   /* if send set is not empty the assign */
2239   /* We've saved all the registers we care about;
2240   * therefore, we may clobber any register not used
2241   * in the calling convention (i.e. anything not in
2242   * fReturn.
2243   */
2244   if (_G.sendSet)
2245     {
2246       iCode *sic;
2247
2248       for (sic = setFirstItem (_G.sendSet); sic;
2249            sic = setNextItem (_G.sendSet))
2250         {
2251           int size, offset = 0;
2252
2253           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2254           size = AOP_SIZE (IC_LEFT (sic));
2255
2256           _startLazyDPSEvaluation ();
2257           while (size--)
2258             {
2259               char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2260                                 FALSE, FALSE, TRUE);
2261                 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2262                 {
2263                     emitcode("mov", "%s,%s", regs390[offset].name, l);
2264                 }
2265                 else if (strcmp (l, fReturn[offset]))
2266                 {
2267                     emitcode ("mov", "%s,%s",
2268                               fReturn[offset],
2269                               l);
2270                 }
2271               offset++;
2272             }
2273           _endLazyDPSEvaluation ();
2274           if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2275           {
2276               size = AOP_SIZE (IC_LEFT (sic));
2277               if (size)
2278               {
2279                  size--;
2280               }
2281               while (size)
2282               {
2283                    size--;
2284                    emitcode("mov", "%s,%s",
2285                                     fReturn[size], regs390[size].name);
2286               }
2287           }
2288           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2289         }
2290       _G.sendSet = NULL;
2291     }  
2292     
2293   if (swapBanks)
2294   {
2295         emitcode ("mov", "psw,#0x%02x", 
2296            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2297   }
2298
2299   /* make the call */
2300   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2301                             OP_SYMBOL (IC_LEFT (ic))->rname :
2302                             OP_SYMBOL (IC_LEFT (ic))->name));
2303
2304   if (swapBanks)
2305   {
2306        emitcode ("mov", "psw,#0x%02x", 
2307           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2308   }
2309
2310   /* if we need assign a result value */
2311   if ((IS_ITEMP (IC_RESULT (ic)) &&
2312        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2313         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2314       IS_TRUE_SYMOP (IC_RESULT (ic)))
2315     {
2316       if (isOperandInFarSpace (IC_RESULT (ic))
2317           && getSize (operandType (IC_RESULT (ic))) <= 2)
2318         {
2319           int size = getSize (operandType (IC_RESULT (ic)));
2320
2321           /* Special case for 1 or 2 byte return in far space. */
2322           MOVA (fReturn[0]);
2323           if (size > 1)
2324             {
2325               emitcode ("mov", "b,%s", fReturn[1]);
2326             }
2327
2328           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2329           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2330
2331           if (size > 1)
2332             {
2333               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2334             }
2335           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2336         }
2337       else
2338         {
2339           _G.accInUse++;
2340           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2341           _G.accInUse--;
2342
2343           assignResultValue (IC_RESULT (ic));
2344
2345           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2346         }
2347     }
2348
2349   /* adjust the stack for parameters if
2350      required */
2351   if (ic->parmBytes)
2352     {
2353       int i;
2354       if (ic->parmBytes > 3)
2355         {
2356           emitcode ("mov", "a,%s", spname);
2357           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2358           emitcode ("mov", "%s,a", spname);
2359         }
2360       else
2361         for (i = 0; i < ic->parmBytes; i++)
2362           emitcode ("dec", "%s", spname);
2363     }
2364
2365   /* if we hade saved some registers then unsave them */
2366   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2367     unsaveRegisters (ic);
2368
2369   /* if register bank was saved then pop them */
2370   if (restoreBank)
2371     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2372 }
2373
2374 /*-----------------------------------------------------------------*/
2375 /* genPcall - generates a call by pointer statement                */
2376 /*-----------------------------------------------------------------*/
2377 static void
2378 genPcall (iCode * ic)
2379 {
2380   sym_link *dtype;
2381   symbol *rlbl = newiTempLabel (NULL);
2382   bool restoreBank=FALSE;
2383
2384   D (emitcode (";", "genPcall ");
2385     );
2386
2387
2388   /* if caller saves & we have not saved then */
2389   if (!ic->regsSaved)
2390     saveRegisters (ic);
2391
2392   /* if we are calling a function that is not using
2393      the same register bank then we need to save the
2394      destination registers on the stack */
2395   dtype = operandType (IC_LEFT (ic));
2396   if (dtype && !IFFUNC_ISNAKED(dtype) &&
2397       IFFUNC_ISISR (currFunc->type) &&
2398       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2399     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2400     restoreBank=TRUE;
2401   }
2402
2403   /* push the return address on to the stack */
2404   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2405   emitcode ("push", "acc");
2406   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2407   emitcode ("push", "acc");
2408
2409   if (options.model == MODEL_FLAT24)
2410     {
2411       emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2412       emitcode ("push", "acc");
2413     }
2414
2415   /* now push the calling address */
2416   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2417
2418   pushSide (IC_LEFT (ic), FPTRSIZE);
2419
2420   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2421
2422   /* if send set is not empty the assign */
2423   if (_G.sendSet)
2424     {
2425       iCode *sic;
2426
2427       for (sic = setFirstItem (_G.sendSet); sic;
2428            sic = setNextItem (_G.sendSet))
2429         {
2430           int size, offset = 0;
2431
2432           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2433           size = AOP_SIZE (IC_LEFT (sic));
2434           _startLazyDPSEvaluation ();
2435           while (size--)
2436             {
2437               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2438                                 FALSE, FALSE, TRUE);
2439               if (strcmp (l, fReturn[offset]))
2440                 {
2441                   emitcode ("mov", "%s,%s",
2442                             fReturn[offset],
2443                             l);
2444                 }
2445               offset++;
2446             }
2447           _endLazyDPSEvaluation ();
2448           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2449         }
2450       _G.sendSet = NULL;
2451     }
2452
2453   emitcode ("ret", "");
2454   emitcode ("", "%05d$:", (rlbl->key + 100));
2455
2456
2457   /* if we need assign a result value */
2458   if ((IS_ITEMP (IC_RESULT (ic)) &&
2459        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2460         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2461       IS_TRUE_SYMOP (IC_RESULT (ic)))
2462     {
2463
2464       _G.accInUse++;
2465       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2466       _G.accInUse--;
2467
2468       assignResultValue (IC_RESULT (ic));
2469
2470       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2471     }
2472
2473   /* adjust the stack for parameters if
2474      required */
2475   if (ic->parmBytes)
2476     {
2477       int i;
2478       if (ic->parmBytes > 3)
2479         {
2480           emitcode ("mov", "a,%s", spname);
2481           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2482           emitcode ("mov", "%s,a", spname);
2483         }
2484       else
2485         for (i = 0; i < ic->parmBytes; i++)
2486           emitcode ("dec", "%s", spname);
2487
2488     }
2489
2490   /* if register bank was saved then unsave them */
2491   if (restoreBank)
2492     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2493   
2494   /* if we hade saved some registers then
2495      unsave them */
2496   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2497     unsaveRegisters (ic);
2498
2499 }
2500
2501 /*-----------------------------------------------------------------*/
2502 /* resultRemat - result  is rematerializable                       */
2503 /*-----------------------------------------------------------------*/
2504 static int
2505 resultRemat (iCode * ic)
2506 {
2507   if (SKIP_IC (ic) || ic->op == IFX)
2508     return 0;
2509
2510   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2511     {
2512       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2513       if (sym->remat && !POINTER_SET (ic))
2514         return 1;
2515     }
2516
2517   return 0;
2518 }
2519
2520 #if defined(__BORLANDC__) || defined(_MSC_VER)
2521 #define STRCASECMP stricmp
2522 #else
2523 #define STRCASECMP strcasecmp
2524 #endif
2525
2526 /*-----------------------------------------------------------------*/
2527 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2528 /*-----------------------------------------------------------------*/
2529 static bool
2530 inExcludeList (char *s)
2531 {
2532   int i = 0;
2533
2534   if (options.excludeRegs[i] &&
2535       STRCASECMP (options.excludeRegs[i], "none") == 0)
2536     return FALSE;
2537
2538   for (i = 0; options.excludeRegs[i]; i++)
2539     {
2540       if (options.excludeRegs[i] &&
2541           STRCASECMP (s, options.excludeRegs[i]) == 0)
2542         return TRUE;
2543     }
2544   return FALSE;
2545 }
2546
2547 /*-----------------------------------------------------------------*/
2548 /* genFunction - generated code for function entry                 */
2549 /*-----------------------------------------------------------------*/
2550 static void
2551 genFunction (iCode * ic)
2552 {
2553   symbol *sym;
2554   sym_link *ftype;
2555   bool   switchedPSW = FALSE;
2556
2557   D (emitcode (";", "genFunction "););
2558
2559   _G.nRegsSaved = 0;
2560   /* create the function header */
2561   emitcode (";", "-----------------------------------------");
2562   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2563   emitcode (";", "-----------------------------------------");
2564
2565   emitcode ("", "%s:", sym->rname);
2566   ftype = operandType (IC_LEFT (ic));
2567
2568   if (IFFUNC_ISNAKED(ftype))
2569   {
2570       emitcode(";", "naked function: no prologue.");
2571       return;
2572   }
2573
2574   /* if critical function then turn interrupts off */
2575   if (IFFUNC_ISCRITICAL (ftype))
2576     emitcode ("clr", "ea");
2577
2578   /* here we need to generate the equates for the
2579      register bank if required */
2580   if (FUNC_REGBANK (ftype) != rbank)
2581     {
2582       int i;
2583
2584       rbank = FUNC_REGBANK (ftype);
2585       for (i = 0; i < ds390_nRegs; i++)
2586         {
2587           if (strcmp (regs390[i].base, "0") == 0)
2588             emitcode ("", "%s = 0x%02x",
2589                       regs390[i].dname,
2590                       8 * rbank + regs390[i].offset);
2591           else
2592             emitcode ("", "%s = %s + 0x%02x",
2593                       regs390[i].dname,
2594                       regs390[i].base,
2595                       8 * rbank + regs390[i].offset);
2596         }
2597     }
2598
2599   /* if this is an interrupt service routine then
2600      save acc, b, dpl, dph  */
2601   if (IFFUNC_ISISR (sym->type))
2602     {
2603
2604       if (!inExcludeList ("acc"))
2605         emitcode ("push", "acc");
2606       if (!inExcludeList ("b"))
2607         emitcode ("push", "b");
2608       if (!inExcludeList ("dpl"))
2609         emitcode ("push", "dpl");
2610       if (!inExcludeList ("dph"))
2611         emitcode ("push", "dph");
2612       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2613         {
2614           emitcode ("push", "dpx");
2615           /* Make sure we're using standard DPTR */
2616           emitcode ("push", "dps");
2617           emitcode ("mov", "dps, #0x00");
2618           if (options.stack10bit)
2619             {
2620               /* This ISR could conceivably use DPTR2. Better save it. */
2621               emitcode ("push", "dpl1");
2622               emitcode ("push", "dph1");
2623               emitcode ("push", "dpx1");
2624               emitcode ("push",  DP2_RESULT_REG);
2625             }
2626         }
2627       /* if this isr has no bank i.e. is going to
2628          run with bank 0 , then we need to save more
2629          registers :-) */
2630       if (!FUNC_REGBANK (sym->type))
2631         {
2632
2633           /* if this function does not call any other
2634              function then we can be economical and
2635              save only those registers that are used */
2636           if (!IFFUNC_HASFCALL(sym->type))
2637             {
2638               int i;
2639
2640               /* if any registers used */
2641               if (sym->regsUsed)
2642                 {
2643                   /* save the registers used */
2644                   for (i = 0; i < sym->regsUsed->size; i++)
2645                     {
2646                       if (bitVectBitValue (sym->regsUsed, i) ||
2647                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2648                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2649                     }
2650                 }
2651
2652             }
2653           else
2654             {
2655               /* this function has  a function call cannot
2656                  determines register usage so we will have to push the
2657                  entire bank */
2658               saveRBank (0, ic, FALSE);
2659             }
2660         }
2661         else
2662         {
2663             /* This ISR uses a non-zero bank.
2664              *
2665              * We assume that the bank is available for our
2666              * exclusive use.
2667              *
2668              * However, if this ISR calls a function which uses some
2669              * other bank, we must save that bank entirely.
2670              */
2671             unsigned long banksToSave = 0;
2672             
2673             if (IFFUNC_HASFCALL(sym->type))
2674             {
2675
2676 #define MAX_REGISTER_BANKS 4
2677
2678                 iCode *i;
2679                 int ix;
2680
2681                 for (i = ic; i; i = i->next)
2682                 {
2683                     if (i->op == ENDFUNCTION)
2684                     {
2685                         /* we got to the end OK. */
2686                         break;
2687                     }
2688                     
2689                     if (i->op == CALL)
2690                     {
2691                         sym_link *dtype;
2692                         
2693                         dtype = operandType (IC_LEFT(i));
2694                         if (dtype 
2695                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2696                         {
2697                              /* Mark this bank for saving. */
2698                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2699                              {
2700                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2701                              }
2702                              else
2703                              {
2704                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2705                              }
2706                              
2707                              /* And note that we don't need to do it in 
2708                               * genCall.
2709                               */
2710                              i->bankSaved = 1;
2711                         }
2712                     }
2713                     if (i->op == PCALL)
2714                     {
2715                         /* This is a mess; we have no idea what
2716                          * register bank the called function might
2717                          * use.
2718                          *
2719                          * The only thing I can think of to do is
2720                          * throw a warning and hope.
2721                          */
2722                         werror(W_FUNCPTR_IN_USING_ISR);   
2723                     }
2724                 }
2725
2726                 if (banksToSave && options.useXstack)
2727                 {
2728                     /* Since we aren't passing it an ic, 
2729                      * saveRBank will assume r0 is available to abuse.
2730                      *
2731                      * So switch to our (trashable) bank now, so
2732                      * the caller's R0 isn't trashed.
2733                      */
2734                     emitcode ("push", "psw");
2735                     emitcode ("mov", "psw,#0x%02x", 
2736                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2737                     switchedPSW = TRUE;
2738                 }
2739                 
2740                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2741                 {
2742                      if (banksToSave & (1 << ix))
2743                      {
2744                          saveRBank(ix, NULL, FALSE);
2745                      }
2746                 }
2747             }
2748             // jwk: this needs a closer look
2749             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2750         }
2751     }
2752   else
2753     {
2754       /* if callee-save to be used for this function
2755          then save the registers being used in this function */
2756       if (IFFUNC_CALLEESAVES(sym->type))
2757         {
2758           int i;
2759
2760           /* if any registers used */
2761           if (sym->regsUsed)
2762             {
2763               /* save the registers used */
2764               for (i = 0; i < sym->regsUsed->size; i++)
2765                 {
2766                   if (bitVectBitValue (sym->regsUsed, i) ||
2767                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2768                     {
2769                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2770                       _G.nRegsSaved++;
2771                     }
2772                 }
2773             }
2774         }
2775     }
2776
2777   /* set the register bank to the desired value */
2778   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2779    && !switchedPSW)
2780     {
2781       emitcode ("push", "psw");
2782       emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2783     }
2784
2785   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2786     {
2787
2788       if (options.useXstack)
2789         {
2790           emitcode ("mov", "r0,%s", spname);
2791           emitcode ("mov", "a,_bp");
2792           emitcode ("movx", "@r0,a");
2793           emitcode ("inc", "%s", spname);
2794         }
2795       else
2796         {
2797           /* set up the stack */
2798           emitcode ("push", "_bp");     /* save the callers stack  */
2799         }
2800       emitcode ("mov", "_bp,%s", spname);
2801     }
2802
2803   /* adjust the stack for the function */
2804   if (sym->stack)
2805     {
2806
2807       int i = sym->stack;
2808       if (i > 256)
2809         werror (W_STACK_OVERFLOW, sym->name);
2810
2811       if (i > 3 && sym->recvSize < 4)
2812         {
2813
2814           emitcode ("mov", "a,sp");
2815           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2816           emitcode ("mov", "sp,a");
2817
2818         }
2819       else
2820         while (i--)
2821           emitcode ("inc", "sp");
2822     }
2823
2824   if (sym->xstack)
2825     {
2826
2827       emitcode ("mov", "a,_spx");
2828       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2829       emitcode ("mov", "_spx,a");
2830     }
2831
2832 }
2833
2834 /*-----------------------------------------------------------------*/
2835 /* genEndFunction - generates epilogue for functions               */
2836 /*-----------------------------------------------------------------*/
2837 static void
2838 genEndFunction (iCode * ic)
2839 {
2840   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2841
2842   D (emitcode (";", "genEndFunction "););
2843
2844   if (IFFUNC_ISNAKED(sym->type))
2845   {
2846       emitcode(";", "naked function: no epilogue.");
2847       return;
2848   }
2849
2850   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2851     {
2852       emitcode ("mov", "%s,_bp", spname);
2853     }
2854
2855   /* if use external stack but some variables were
2856      added to the local stack then decrement the
2857      local stack */
2858   if (options.useXstack && sym->stack)
2859     {
2860       emitcode ("mov", "a,sp");
2861       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2862       emitcode ("mov", "sp,a");
2863     }
2864
2865
2866   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2867     {
2868       if (options.useXstack)
2869         {
2870           emitcode ("mov", "r0,%s", spname);
2871           emitcode ("movx", "a,@r0");
2872           emitcode ("mov", "_bp,a");
2873           emitcode ("dec", "%s", spname);
2874         }
2875       else
2876         {
2877           emitcode ("pop", "_bp");
2878         }
2879     }
2880
2881   /* restore the register bank  */
2882   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2883   {
2884     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2885      || !options.useXstack)
2886     {
2887         /* Special case of ISR using non-zero bank with useXstack
2888          * is handled below.
2889          */
2890         emitcode ("pop", "psw");
2891     }
2892   }
2893
2894   if (IFFUNC_ISISR (sym->type))
2895     {
2896
2897       /* now we need to restore the registers */
2898       /* if this isr has no bank i.e. is going to
2899          run with bank 0 , then we need to save more
2900          registers :-) */
2901       if (!FUNC_REGBANK (sym->type))
2902         {
2903           /* if this function does not call any other
2904              function then we can be economical and
2905              save only those registers that are used */
2906           if (!IFFUNC_HASFCALL(sym->type))
2907             {
2908               int i;
2909
2910               /* if any registers used */
2911               if (sym->regsUsed)
2912                 {
2913                   /* save the registers used */
2914                   for (i = sym->regsUsed->size; i >= 0; i--)
2915                     {
2916                       if (bitVectBitValue (sym->regsUsed, i) ||
2917                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2918                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2919                     }
2920                 }
2921
2922             }
2923           else
2924             {
2925               /* this function has  a function call cannot
2926                  determines register usage so we will have to pop the
2927                  entire bank */
2928               unsaveRBank (0, ic, FALSE);
2929             }
2930         }
2931         else
2932         {
2933             /* This ISR uses a non-zero bank.
2934              *
2935              * Restore any register banks saved by genFunction
2936              * in reverse order.
2937              */
2938           // jwk: this needs a closer look
2939             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2940             int ix;
2941           
2942             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2943             {
2944                 if (savedBanks & (1 << ix))
2945                 {
2946                     unsaveRBank(ix, NULL, FALSE);
2947                 }
2948             }
2949             
2950             if (options.useXstack)
2951             {
2952                 /* Restore bank AFTER calling unsaveRBank,
2953                  * since it can trash r0.
2954                  */
2955                 emitcode ("pop", "psw");
2956             }
2957         }
2958
2959       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2960         {
2961           if (options.stack10bit)
2962             {
2963               emitcode ("pop", DP2_RESULT_REG);
2964               emitcode ("pop", "dpx1");
2965               emitcode ("pop", "dph1");
2966               emitcode ("pop", "dpl1");
2967             }
2968           emitcode ("pop", "dps");
2969           emitcode ("pop", "dpx");
2970         }
2971       if (!inExcludeList ("dph"))
2972         emitcode ("pop", "dph");
2973       if (!inExcludeList ("dpl"))
2974         emitcode ("pop", "dpl");
2975       if (!inExcludeList ("b"))
2976         emitcode ("pop", "b");
2977       if (!inExcludeList ("acc"))
2978         emitcode ("pop", "acc");
2979
2980       if (IFFUNC_ISCRITICAL (sym->type))
2981         emitcode ("setb", "ea");
2982
2983       /* if debug then send end of function */
2984       if (options.debug && currFunc) {
2985           _G.debugLine = 1;
2986           emitcode ("", "C$%s$%d$%d$%d ==.",
2987                     FileBaseName (ic->filename), currFunc->lastLine,
2988                     ic->level, ic->block);
2989           if (IS_STATIC (currFunc->etype))
2990             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2991           else
2992             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2993           _G.debugLine = 0;
2994         }
2995
2996       emitcode ("reti", "");
2997     }
2998   else
2999     {
3000       if (IFFUNC_ISCRITICAL (sym->type))
3001         emitcode ("setb", "ea");
3002
3003       if (IFFUNC_CALLEESAVES(sym->type))
3004         {
3005           int i;
3006
3007           /* if any registers used */
3008           if (sym->regsUsed)
3009             {
3010               /* save the registers used */
3011               for (i = sym->regsUsed->size; i >= 0; i--)
3012                 {
3013                   if (bitVectBitValue (sym->regsUsed, i) ||
3014                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3015                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3016                 }
3017             }
3018
3019         }
3020
3021       /* if debug then send end of function */
3022       if (options.debug && currFunc)
3023         {
3024           _G.debugLine = 1;
3025           emitcode ("", "C$%s$%d$%d$%d ==.",
3026                     FileBaseName (ic->filename), currFunc->lastLine,
3027                     ic->level, ic->block);
3028           if (IS_STATIC (currFunc->etype))
3029             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3030           else
3031             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3032           _G.debugLine = 0;
3033         }
3034
3035       emitcode ("ret", "");
3036     }
3037
3038 }
3039
3040 /*-----------------------------------------------------------------*/
3041 /* genRet - generate code for return statement                     */
3042 /*-----------------------------------------------------------------*/
3043 static void
3044 genRet (iCode * ic)
3045 {
3046   int size, offset = 0, pushed = 0;
3047
3048   D (emitcode (";", "genRet ");
3049     );
3050
3051   /* if we have no return value then
3052      just generate the "ret" */
3053   if (!IC_LEFT (ic))
3054     goto jumpret;
3055
3056   /* we have something to return then
3057      move the return value into place */
3058   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3059   size = AOP_SIZE (IC_LEFT (ic));
3060
3061   _startLazyDPSEvaluation ();
3062   while (size--)
3063     {
3064       char *l;
3065       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3066         {
3067           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3068                       FALSE, TRUE, FALSE);
3069           emitcode ("push", "%s", l);
3070           pushed++;
3071         }
3072       else
3073         {
3074           /* Since A is the last element of fReturn,
3075            * is is OK to clobber it in the aopGet.
3076            */
3077           l = aopGet (AOP (IC_LEFT (ic)), offset,
3078                       FALSE, FALSE, TRUE);
3079           if (strcmp (fReturn[offset], l))
3080             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3081         }
3082     }
3083   _endLazyDPSEvaluation ();
3084
3085   if (pushed)
3086     {
3087       while (pushed)
3088         {
3089           pushed--;
3090           if (strcmp (fReturn[pushed], "a"))
3091             emitcode ("pop", fReturn[pushed]);
3092           else
3093             emitcode ("pop", "acc");
3094         }
3095     }
3096   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3097
3098 jumpret:
3099   /* generate a jump to the return label
3100      if the next is not the return statement */
3101   if (!(ic->next && ic->next->op == LABEL &&
3102         IC_LABEL (ic->next) == returnLabel))
3103
3104     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3105
3106 }
3107
3108 /*-----------------------------------------------------------------*/
3109 /* genLabel - generates a label                                    */
3110 /*-----------------------------------------------------------------*/
3111 static void
3112 genLabel (iCode * ic)
3113 {
3114   /* special case never generate */
3115   if (IC_LABEL (ic) == entryLabel)
3116     return;
3117
3118   D (emitcode (";", "genLabel ");
3119     );
3120
3121   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3122 }
3123
3124 /*-----------------------------------------------------------------*/
3125 /* genGoto - generates a ljmp                                      */
3126 /*-----------------------------------------------------------------*/
3127 static void
3128 genGoto (iCode * ic)
3129 {
3130   D (emitcode (";", "genGoto ");
3131     );
3132   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3133 }
3134
3135 /*-----------------------------------------------------------------*/
3136 /* findLabelBackwards: walks back through the iCode chain looking  */
3137 /* for the given label. Returns number of iCode instructions     */
3138 /* between that label and given ic.          */
3139 /* Returns zero if label not found.          */
3140 /*-----------------------------------------------------------------*/
3141 static int
3142 findLabelBackwards (iCode * ic, int key)
3143 {
3144   int count = 0;
3145
3146   while (ic->prev)
3147     {
3148       ic = ic->prev;
3149       count++;
3150
3151       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3152         {
3153           /* printf("findLabelBackwards = %d\n", count); */
3154           return count;
3155         }
3156     }
3157
3158   return 0;
3159 }
3160
3161 /*-----------------------------------------------------------------*/
3162 /* genPlusIncr :- does addition with increment if possible         */
3163 /*-----------------------------------------------------------------*/
3164 static bool
3165 genPlusIncr (iCode * ic)
3166 {
3167   unsigned int icount;
3168   unsigned int size = getDataSize (IC_RESULT (ic));
3169
3170   /* will try to generate an increment */
3171   /* if the right side is not a literal
3172      we cannot */
3173   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3174     return FALSE;
3175
3176   /* if the literal value of the right hand side
3177      is greater than 4 then it is not worth it */
3178   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3179     return FALSE;
3180
3181   /* if increment 16 bits in register */
3182   if (
3183        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3184        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3185        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3186        (size > 1) &&
3187        (icount == 1))
3188     {
3189       symbol *tlbl;
3190       int emitTlbl;
3191       int labelRange;
3192
3193       /* If the next instruction is a goto and the goto target
3194        * is <= 5 instructions previous to this, we can generate
3195        * jumps straight to that target.
3196        */
3197       if (ic->next && ic->next->op == GOTO
3198           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3199           && labelRange <= 5)
3200         {
3201           emitcode (";", "tail increment optimized (range %d)", labelRange);
3202           tlbl = IC_LABEL (ic->next);
3203           emitTlbl = 0;
3204         }
3205       else
3206         {
3207           tlbl = newiTempLabel (NULL);
3208           emitTlbl = 1;
3209         }
3210       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3211       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3212           IS_AOP_PREG (IC_RESULT (ic)))
3213         emitcode ("cjne", "%s,#0x00,%05d$"
3214                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3215                   ,tlbl->key + 100);
3216       else
3217         {
3218           emitcode ("clr", "a");
3219           emitcode ("cjne", "a,%s,%05d$"
3220                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3221                     ,tlbl->key + 100);
3222         }
3223
3224       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3225       if (size > 2)
3226         {
3227           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3228               IS_AOP_PREG (IC_RESULT (ic)))
3229             emitcode ("cjne", "%s,#0x00,%05d$"
3230                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3231                       ,tlbl->key + 100);
3232           else
3233             emitcode ("cjne", "a,%s,%05d$"
3234                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3235                       ,tlbl->key + 100);
3236
3237           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3238         }
3239       if (size > 3)
3240         {
3241           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3242               IS_AOP_PREG (IC_RESULT (ic)))
3243             emitcode ("cjne", "%s,#0x00,%05d$"
3244                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3245                       ,tlbl->key + 100);
3246           else
3247             {
3248               emitcode ("cjne", "a,%s,%05d$"
3249                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3250                         ,tlbl->key + 100);
3251             }
3252           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3253         }
3254
3255       if (emitTlbl)
3256         {
3257           emitcode ("", "%05d$:", tlbl->key + 100);
3258         }
3259       return TRUE;
3260     }
3261
3262   /* if the sizes are greater than 1 then we cannot */
3263   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3264       AOP_SIZE (IC_LEFT (ic)) > 1)
3265     return FALSE;
3266
3267   /* we can if the aops of the left & result match or
3268      if they are in registers and the registers are the
3269      same */
3270   if (
3271        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3272        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3273        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3274     {
3275
3276       if (icount > 3)
3277         {
3278           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3279           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3280           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3281         }
3282       else
3283         {
3284
3285           _startLazyDPSEvaluation ();
3286           while (icount--)
3287             {
3288               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3289             }
3290           _endLazyDPSEvaluation ();
3291         }
3292
3293       return TRUE;
3294     }
3295
3296   return FALSE;
3297 }
3298
3299 /*-----------------------------------------------------------------*/
3300 /* outBitAcc - output a bit in acc                                 */
3301 /*-----------------------------------------------------------------*/
3302 static void
3303 outBitAcc (operand * result)
3304 {
3305   symbol *tlbl = newiTempLabel (NULL);
3306   /* if the result is a bit */
3307   if (AOP_TYPE (result) == AOP_CRY)
3308     {
3309       aopPut (AOP (result), "a", 0);
3310     }
3311   else
3312     {
3313       emitcode ("jz", "%05d$", tlbl->key + 100);
3314       emitcode ("mov", "a,%s", one);
3315       emitcode ("", "%05d$:", tlbl->key + 100);
3316       outAcc (result);
3317     }
3318 }
3319
3320 /*-----------------------------------------------------------------*/
3321 /* genPlusBits - generates code for addition of two bits           */
3322 /*-----------------------------------------------------------------*/
3323 static void
3324 genPlusBits (iCode * ic)
3325 {
3326   D (emitcode (";", "genPlusBits ");
3327     );
3328   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3329     {
3330       symbol *lbl = newiTempLabel (NULL);
3331       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3332       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3333       emitcode ("cpl", "c");
3334       emitcode ("", "%05d$:", (lbl->key + 100));
3335       outBitC (IC_RESULT (ic));
3336     }
3337   else
3338     {
3339       emitcode ("clr", "a");
3340       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3341       emitcode ("rlc", "a");
3342       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3343       emitcode ("addc", "a,#0x00");
3344       outAcc (IC_RESULT (ic));
3345     }
3346 }
3347
3348 static void
3349 adjustArithmeticResult (iCode * ic)
3350 {
3351   if (opIsGptr (IC_RESULT (ic)) &&
3352       opIsGptr (IC_LEFT (ic)) &&
3353       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3354     {
3355       aopPut (AOP (IC_RESULT (ic)),
3356               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3357               GPTRSIZE - 1);
3358     }
3359
3360   if (opIsGptr (IC_RESULT (ic)) &&
3361       opIsGptr (IC_RIGHT (ic)) &&
3362       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3363     {
3364       aopPut (AOP (IC_RESULT (ic)),
3365             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3366               GPTRSIZE - 1);
3367     }
3368
3369   if (opIsGptr (IC_RESULT (ic)) &&
3370       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3371       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3372       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3373       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3374     {
3375       char buffer[5];
3376       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3377       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3378     }
3379 }
3380
3381 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3382       // Please don't bring it back without a really good reason.
3383 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3384 // (because all three operands are in far space).
3385 #define AOP_OP_3(ic) \
3386     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3387     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3388     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3389               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3390     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3391         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3392     { \
3393         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3394         fprintf(stderr,                                  \
3395                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3396     }
3397 #endif
3398
3399 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3400 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3401 // will be set TRUE. The caller must then handle the case specially, noting
3402 // that the IC_RESULT operand is not aopOp'd.
3403 #define AOP_OP_3_NOFATAL(ic, rc) \
3404     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3405     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3406     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3407         isOperandInFarSpace(IC_RESULT(ic))) \
3408     { \
3409        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3410        rc = TRUE; \
3411     }  \
3412     else \
3413     { \
3414        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3415                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3416        rc = FALSE; \
3417        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3418            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3419        { \
3420             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3421             fprintf(stderr,                                  \
3422                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3423        } \
3424     }
3425
3426 // aopOp the left & right operands of an ic.
3427 #define AOP_OP_2(ic) \
3428     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3429     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3430
3431 // convienience macro.
3432 #define AOP_SET_LOCALS(ic) \
3433     left = IC_LEFT(ic); \
3434     right = IC_RIGHT(ic); \
3435     result = IC_RESULT(ic);
3436
3437
3438 // Given an integer value of pushedSize bytes on the stack,
3439 // adjust it to be resultSize bytes, either by discarding
3440 // the most significant bytes or by zero-padding.
3441 //
3442 // On exit from this macro, pushedSize will have been adjusted to
3443 // equal resultSize, and ACC may be trashed.
3444 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3445       /* If the pushed data is bigger than the result,          \
3446        * simply discard unused bytes. Icky, but works.          \
3447        */                                                       \
3448       while (pushedSize > resultSize)                           \
3449       {                                                         \
3450           D (emitcode (";", "discarding unused result byte."););\
3451           emitcode ("pop", "acc");                              \
3452           pushedSize--;                                         \
3453       }                                                         \
3454       if (pushedSize < resultSize)                              \
3455       {                                                         \
3456           emitcode ("clr", "a");                                \
3457           /* Conversly, we haven't pushed enough here.          \
3458            * just zero-pad, and all is well.                    \
3459            */                                                   \
3460           while (pushedSize < resultSize)                       \
3461           {                                                     \
3462               emitcode("push", "acc");                          \
3463               pushedSize++;                                     \
3464           }                                                     \
3465       }                                                         \
3466       assert(pushedSize == resultSize);
3467
3468 /*-----------------------------------------------------------------*/
3469 /* genPlus - generates code for addition                           */
3470 /*-----------------------------------------------------------------*/
3471 static void
3472 genPlus (iCode * ic)
3473 {
3474   int size, offset = 0;
3475   bool pushResult = FALSE;
3476   int rSize;
3477
3478   D (emitcode (";", "genPlus "););
3479
3480   /* special cases :- */
3481
3482   AOP_OP_3_NOFATAL (ic, pushResult);
3483   if (pushResult)
3484     {
3485       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3486     }
3487
3488   if (!pushResult)
3489     {
3490       /* if literal, literal on the right or
3491          if left requires ACC or right is already
3492          in ACC */
3493       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3494        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3495           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3496         {
3497           operand *t = IC_RIGHT (ic);
3498           IC_RIGHT (ic) = IC_LEFT (ic);
3499           IC_LEFT (ic) = t;
3500           emitcode (";", "Swapped plus args.");
3501         }
3502
3503       /* if both left & right are in bit
3504          space */
3505       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3506           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3507         {
3508           genPlusBits (ic);
3509           goto release;
3510         }
3511
3512       /* if left in bit space & right literal */
3513       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3514           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3515         {
3516           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3517           /* if result in bit space */
3518           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3519             {
3520               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3521                 emitcode ("cpl", "c");
3522               outBitC (IC_RESULT (ic));
3523             }
3524           else
3525             {
3526               size = getDataSize (IC_RESULT (ic));
3527               _startLazyDPSEvaluation ();
3528               while (size--)
3529                 {
3530                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3531                   emitcode ("addc", "a,#00");
3532                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3533                 }
3534               _endLazyDPSEvaluation ();
3535             }
3536           goto release;
3537         }
3538
3539       /* if I can do an increment instead
3540          of add then GOOD for ME */
3541       if (genPlusIncr (ic) == TRUE)
3542         {
3543           emitcode (";", "did genPlusIncr");
3544           goto release;
3545         }
3546
3547     }
3548   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3549
3550   _startLazyDPSEvaluation ();
3551   while (size--)
3552     {
3553       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3554         {
3555           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3556           if (offset == 0)
3557             emitcode ("add", "a,%s",
3558                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3559           else
3560             emitcode ("addc", "a,%s",
3561                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3562         }
3563       else
3564         {
3565           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3566           {
3567               /* right is going to use ACC or we would have taken the
3568                * above branch.
3569                */
3570               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3571        TR_AP("#3");
3572               D(emitcode(";", "+ AOP_ACC special case."););
3573               emitcode("xch", "a, %s", DP2_RESULT_REG);
3574           }
3575           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3576           if (offset == 0)
3577           {
3578             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3579             {
3580          TR_AP("#4");
3581                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3582             }
3583             else
3584             {
3585                 emitcode ("add", "a,%s",
3586                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3587             }
3588           }
3589           else
3590           {
3591             emitcode ("addc", "a,%s",
3592                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3593           }
3594         }
3595       if (!pushResult)
3596         {
3597           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3598         }
3599       else
3600         {
3601           emitcode ("push", "acc");
3602         }
3603       offset++;
3604     }
3605   _endLazyDPSEvaluation ();
3606
3607   if (pushResult)
3608     {
3609       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3610
3611       size = getDataSize (IC_LEFT (ic));
3612       rSize = getDataSize (IC_RESULT (ic));
3613
3614       ADJUST_PUSHED_RESULT(size, rSize);
3615
3616       _startLazyDPSEvaluation ();
3617       while (size--)
3618         {
3619           emitcode ("pop", "acc");
3620           aopPut (AOP (IC_RESULT (ic)), "a", size);
3621         }
3622       _endLazyDPSEvaluation ();
3623     }
3624
3625   adjustArithmeticResult (ic);
3626
3627 release:
3628   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3629   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3630   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3631 }
3632
3633 /*-----------------------------------------------------------------*/
3634 /* genMinusDec :- does subtraction with deccrement if possible     */
3635 /*-----------------------------------------------------------------*/
3636 static bool
3637 genMinusDec (iCode * ic)
3638 {
3639   unsigned int icount;
3640   unsigned int size = getDataSize (IC_RESULT (ic));
3641
3642   /* will try to generate an increment */
3643   /* if the right side is not a literal
3644      we cannot */
3645   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3646     return FALSE;
3647
3648   /* if the literal value of the right hand side
3649      is greater than 4 then it is not worth it */
3650   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3651     return FALSE;
3652
3653   /* if decrement 16 bits in register */
3654   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3655       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3656       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3657       (size > 1) &&
3658       (icount == 1))
3659     {
3660       symbol *tlbl;
3661       int emitTlbl;
3662       int labelRange;
3663
3664       /* If the next instruction is a goto and the goto target
3665          * is <= 5 instructions previous to this, we can generate
3666          * jumps straight to that target.
3667        */
3668       if (ic->next && ic->next->op == GOTO
3669           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3670           && labelRange <= 5)
3671         {
3672           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3673           tlbl = IC_LABEL (ic->next);
3674           emitTlbl = 0;
3675         }
3676       else
3677         {
3678           tlbl = newiTempLabel (NULL);
3679           emitTlbl = 1;
3680         }
3681
3682       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3683       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3684           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3685           IS_AOP_PREG (IC_RESULT (ic)))
3686         emitcode ("cjne", "%s,#0xff,%05d$"
3687                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3688                   ,tlbl->key + 100);
3689       else
3690         {
3691           emitcode ("mov", "a,#0xff");
3692           emitcode ("cjne", "a,%s,%05d$"
3693                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3694                     ,tlbl->key + 100);
3695         }
3696       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3697       if (size > 2)
3698         {
3699           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3700               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3701               IS_AOP_PREG (IC_RESULT (ic)))
3702             emitcode ("cjne", "%s,#0xff,%05d$"
3703                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3704                       ,tlbl->key + 100);
3705           else
3706             {
3707               emitcode ("cjne", "a,%s,%05d$"
3708                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3709                         ,tlbl->key + 100);
3710             }
3711           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3712         }
3713       if (size > 3)
3714         {
3715           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3716               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3717               IS_AOP_PREG (IC_RESULT (ic)))
3718             emitcode ("cjne", "%s,#0xff,%05d$"
3719                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3720                       ,tlbl->key + 100);
3721           else
3722             {
3723               emitcode ("cjne", "a,%s,%05d$"
3724                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3725                         ,tlbl->key + 100);
3726             }
3727           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3728         }
3729       if (emitTlbl)
3730         {
3731           emitcode ("", "%05d$:", tlbl->key + 100);
3732         }
3733       return TRUE;
3734     }
3735
3736   /* if the sizes are greater than 1 then we cannot */
3737   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3738       AOP_SIZE (IC_LEFT (ic)) > 1)
3739     return FALSE;
3740
3741   /* we can if the aops of the left & result match or
3742      if they are in registers and the registers are the
3743      same */
3744   if (
3745        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3746        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3747        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3748     {
3749
3750       _startLazyDPSEvaluation ();
3751       while (icount--)
3752         {
3753           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3754         }
3755       _endLazyDPSEvaluation ();
3756
3757       return TRUE;
3758     }
3759
3760   return FALSE;
3761 }
3762
3763 /*-----------------------------------------------------------------*/
3764 /* addSign - complete with sign                                    */
3765 /*-----------------------------------------------------------------*/
3766 static void
3767 addSign (operand * result, int offset, int sign)
3768 {
3769   int size = (getDataSize (result) - offset);
3770   if (size > 0)
3771     {
3772       _startLazyDPSEvaluation();
3773       if (sign)
3774         {
3775           emitcode ("rlc", "a");
3776           emitcode ("subb", "a,acc");
3777           while (size--)
3778           {
3779             aopPut (AOP (result), "a", offset++);
3780           }
3781         }
3782       else
3783       {
3784         while (size--)
3785         {
3786           aopPut (AOP (result), zero, offset++);
3787         }
3788       }
3789       _endLazyDPSEvaluation();
3790     }
3791 }
3792
3793 /*-----------------------------------------------------------------*/
3794 /* genMinusBits - generates code for subtraction  of two bits      */
3795 /*-----------------------------------------------------------------*/
3796 static void
3797 genMinusBits (iCode * ic)
3798 {
3799   symbol *lbl = newiTempLabel (NULL);
3800
3801   D (emitcode (";", "genMinusBits "););
3802
3803   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3804     {
3805       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3806       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3807       emitcode ("cpl", "c");
3808       emitcode ("", "%05d$:", (lbl->key + 100));
3809       outBitC (IC_RESULT (ic));
3810     }
3811   else
3812     {
3813       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3814       emitcode ("subb", "a,acc");
3815       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3816       emitcode ("inc", "a");
3817       emitcode ("", "%05d$:", (lbl->key + 100));
3818       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3819       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3820     }
3821 }
3822
3823 /*-----------------------------------------------------------------*/
3824 /* genMinus - generates code for subtraction                       */
3825 /*-----------------------------------------------------------------*/
3826 static void
3827 genMinus (iCode * ic)
3828 {
3829   int size, offset = 0;
3830   int rSize;
3831   unsigned long lit = 0L;
3832   bool pushResult = FALSE;
3833
3834   D (emitcode (";", "genMinus "););
3835
3836   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3837   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3838   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3839       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3840     {
3841       pushResult = TRUE;
3842     }
3843   else
3844     {
3845       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3846
3847       /* special cases :- */
3848       /* if both left & right are in bit space */
3849       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3850           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3851         {
3852           genMinusBits (ic);
3853           goto release;
3854         }
3855
3856       /* if I can do an decrement instead
3857          of subtract then GOOD for ME */
3858       if (genMinusDec (ic) == TRUE)
3859         goto release;
3860
3861     }
3862
3863   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3864
3865   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3866     {
3867       CLRC;
3868     }
3869   else
3870     {
3871       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3872       lit = -(long) lit;
3873     }
3874
3875
3876   /* if literal, add a,#-lit, else normal subb */
3877   _startLazyDPSEvaluation ();
3878   while (size--)
3879     {
3880       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3881       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3882         emitcode ("subb", "a,%s",
3883                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3884       else
3885         {
3886           /* first add without previous c */
3887           if (!offset) {
3888             if (!size && lit==-1) {
3889               emitcode ("dec", "a");
3890             } else {
3891               emitcode ("add", "a,#0x%02x",
3892                         (unsigned int) (lit & 0x0FFL));
3893             }
3894           } else {
3895             emitcode ("addc", "a,#0x%02x",
3896                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3897           }
3898         }
3899
3900       if (pushResult)
3901         {
3902           emitcode ("push", "acc");
3903         }
3904       else
3905         {
3906           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3907         }
3908       offset++;
3909     }
3910   _endLazyDPSEvaluation ();
3911
3912   if (pushResult)
3913     {
3914       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3915
3916       size = getDataSize (IC_LEFT (ic));
3917       rSize = getDataSize (IC_RESULT (ic));
3918
3919       ADJUST_PUSHED_RESULT(size, rSize);
3920
3921       _startLazyDPSEvaluation ();
3922       while (size--)
3923         {
3924           emitcode ("pop", "acc");
3925           aopPut (AOP (IC_RESULT (ic)), "a", size);
3926         }
3927       _endLazyDPSEvaluation ();
3928     }
3929
3930   adjustArithmeticResult (ic);
3931
3932 release:
3933   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3934   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3935   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3936 }
3937
3938
3939 /*-----------------------------------------------------------------*/
3940 /* genMultbits :- multiplication of bits                           */
3941 /*-----------------------------------------------------------------*/
3942 static void
3943 genMultbits (operand * left,
3944              operand * right,
3945              operand * result,
3946              iCode   * ic)
3947 {
3948   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3949   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3950   aopOp(result, ic, TRUE, FALSE);
3951   outBitC (result);
3952 }
3953
3954
3955 /*-----------------------------------------------------------------*/
3956 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3957 /*-----------------------------------------------------------------*/
3958 static void
3959 genMultOneByte (operand * left,
3960                 operand * right,
3961                 operand * result,
3962                 iCode   * ic)
3963 {
3964   sym_link *opetype = operandType (result);
3965   symbol *lbl;
3966
3967
3968   /* (if two literals: the value is computed before) */
3969   /* if one literal, literal on the right */
3970   if (AOP_TYPE (left) == AOP_LIT)
3971     {
3972       operand *t = right;
3973       right = left;
3974       left = t;
3975       emitcode (";", "swapped left and right");
3976     }
3977
3978   if (SPEC_USIGN(opetype)
3979       // ignore the sign of left and right, what else can we do?
3980       || (SPEC_USIGN(operandType(left)) && 
3981           SPEC_USIGN(operandType(right)))) {
3982     // just an unsigned 8*8=8/16 multiply
3983     //emitcode (";","unsigned");
3984     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3985     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3986     emitcode ("mul", "ab");
3987    
3988     _G.accInUse++;
3989     aopOp(result, ic, TRUE, FALSE);
3990       
3991       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
3992       {
3993           // this should never happen
3994           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3995                    AOP_SIZE(result), __FILE__, lineno);
3996           exit (1);
3997       }      
3998       
3999     aopPut (AOP (result), "a", 0);
4000     _G.accInUse--;
4001     if (AOP_SIZE(result)==2) 
4002     {
4003       aopPut (AOP (result), "b", 1);
4004     }
4005     return;
4006   }
4007
4008   // we have to do a signed multiply
4009
4010   emitcode (";", "signed");
4011   emitcode ("clr", "F0"); // reset sign flag
4012   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
4013
4014   lbl=newiTempLabel(NULL);
4015   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
4016   // left side is negative, 8-bit two's complement, this fails for -128
4017   emitcode ("setb", "F0"); // set sign flag
4018   emitcode ("cpl", "a");
4019   emitcode ("inc", "a");
4020
4021   emitcode ("", "%05d$:", lbl->key+100);
4022
4023   /* if literal */
4024   if (AOP_TYPE(right)==AOP_LIT) {
4025     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4026     /* AND literal negative */
4027     if ((int) val < 0) {
4028       emitcode ("cpl", "F0"); // complement sign flag
4029       emitcode ("mov", "b,#0x%02x", -val);
4030     } else {
4031       emitcode ("mov", "b,#0x%02x", val);
4032     }
4033   } else {
4034     lbl=newiTempLabel(NULL);
4035     emitcode ("mov", "b,a");
4036     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4037     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4038     // right side is negative, 8-bit two's complement
4039     emitcode ("cpl", "F0"); // complement sign flag
4040     emitcode ("cpl", "a");
4041     emitcode ("inc", "a");
4042     emitcode ("", "%05d$:", lbl->key+100);
4043   }
4044   emitcode ("mul", "ab");
4045     
4046   _G.accInUse++;
4047   aopOp(result, ic, TRUE, FALSE);
4048     
4049   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4050   {
4051     // this should never happen
4052       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4053                AOP_SIZE(result), __FILE__, lineno);
4054       exit (1);
4055   }    
4056     
4057   lbl=newiTempLabel(NULL);
4058   emitcode ("jnb", "F0,%05d$", lbl->key+100);
4059   // only ONE op was negative, we have to do a 8/16-bit two's complement
4060   emitcode ("cpl", "a"); // lsb
4061   if (AOP_SIZE(result)==1) {
4062     emitcode ("inc", "a");
4063   } else {
4064     emitcode ("add", "a,#1");
4065     emitcode ("xch", "a,b");
4066     emitcode ("cpl", "a"); // msb
4067     emitcode ("addc", "a,#0");
4068     emitcode ("xch", "a,b");
4069   }
4070
4071   emitcode ("", "%05d$:", lbl->key+100);
4072   aopPut (AOP (result), "a", 0);
4073   _G.accInUse--;
4074   if (AOP_SIZE(result)==2) {
4075     aopPut (AOP (result), "b", 1);
4076   }
4077 }
4078
4079 /*-----------------------------------------------------------------*/
4080 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4081 /*-----------------------------------------------------------------*/
4082 static void genMultTwoByte (operand *left, operand *right, 
4083                             operand *result, iCode *ic)
4084 {
4085         sym_link *retype = getSpec(operandType(right));
4086         sym_link *letype = getSpec(operandType(left));
4087         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4088         symbol *lbl;
4089
4090         if (AOP_TYPE (left) == AOP_LIT) {
4091                 operand *t = right;
4092                 right = left;
4093                 left = t;
4094         }
4095         /* load up MB with right */
4096         if (!umult) {
4097                 emitcode("clr","F0");
4098                 if (AOP_TYPE(right) == AOP_LIT) {
4099                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4100                         if (val < 0) {
4101                                 emitcode("setb","F0");
4102                                 val = -val;
4103                         }
4104                         emitcode ("mov","mb,#0x%02x",val & 0xff);
4105                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);                    
4106                 } else {
4107                         lbl = newiTempLabel(NULL);
4108                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4109                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4110                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4111                         emitcode ("xch", "a,b");
4112                         emitcode ("cpl","a");
4113                         emitcode ("add", "a,#1");
4114                         emitcode ("xch", "a,b");
4115                         emitcode ("cpl", "a"); // msb
4116                         emitcode ("addc", "a,#0");
4117                         emitcode ("setb","F0");
4118                         emitcode ("","%05d$:",lbl->key+100);
4119                         emitcode ("mov","mb,b");
4120                         emitcode ("mov","mb,a");
4121                 }
4122         } else {
4123                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4124                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4125         }
4126         /* load up MA with left */
4127         if (!umult) {
4128                 lbl = newiTempLabel(NULL);
4129                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4130                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4131                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4132                 emitcode ("xch", "a,b");
4133                 emitcode ("cpl","a");
4134                 emitcode ("add", "a,#1");
4135                 emitcode ("xch", "a,b");
4136                 emitcode ("cpl", "a"); // msb
4137                 emitcode ("addc","a,#0");
4138                 emitcode ("jbc","F0,%05d$",lbl->key+100);
4139                 emitcode ("setb","F0");
4140                 emitcode ("","%05d$:",lbl->key+100);
4141                 emitcode ("mov","ma,b");
4142                 emitcode ("mov","ma,a");
4143         } else {
4144                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4145                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4146         }
4147         /* wait for multiplication to finish */
4148         lbl = newiTempLabel(NULL);
4149         emitcode("","%05d$:", lbl->key+100);
4150         emitcode("mov","a,mcnt1");
4151         emitcode("anl","a,#0x80");
4152         emitcode("jnz","%05d$",lbl->key+100);
4153         
4154         freeAsmop (left, NULL, ic, TRUE);
4155         freeAsmop (right, NULL, ic,TRUE);
4156         aopOp(result, ic, TRUE, FALSE);
4157
4158         /* if unsigned then simple */   
4159         if (umult) {
4160                 emitcode ("mov","a,ma");
4161                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4162                 emitcode ("mov","a,ma");
4163                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4164                 aopPut(AOP(result),"ma",1);
4165                 aopPut(AOP(result),"ma",0);
4166         } else {
4167                 emitcode("push","ma");
4168                 emitcode("push","ma");
4169                 emitcode("push","ma");
4170                 MOVA("ma");
4171                 /* negate result if needed */
4172                 lbl = newiTempLabel(NULL);      
4173                 emitcode("jnb","F0,%05d$",lbl->key+100);
4174                 emitcode("cpl","a");
4175                 emitcode("add","a,#1");
4176                 emitcode("","%05d$:", lbl->key+100);
4177                 if (AOP_TYPE(result) == AOP_ACC)
4178                 {
4179                     D(emitcode(";", "ACC special case."););
4180                     /* We know result is the only live aop, and 
4181                      * it's obviously not a DPTR2, so AP is available.
4182                      */
4183                     emitcode("mov", "%s,acc", DP2_RESULT_REG);
4184                 }
4185                 else
4186                 {
4187                     aopPut(AOP(result),"a",0);
4188                 }
4189             
4190                 emitcode("pop","acc");
4191                 lbl = newiTempLabel(NULL);      
4192                 emitcode("jnb","F0,%05d$",lbl->key+100);
4193                 emitcode("cpl","a");
4194                 emitcode("addc","a,#0");
4195                 emitcode("","%05d$:", lbl->key+100);
4196                 aopPut(AOP(result),"a",1);
4197                 emitcode("pop","acc");
4198                 if (AOP_SIZE(result) >= 3) {
4199                         lbl = newiTempLabel(NULL);      
4200                         emitcode("jnb","F0,%05d$",lbl->key+100);
4201                         emitcode("cpl","a");
4202                         emitcode("addc","a,#0");                        
4203                         emitcode("","%05d$:", lbl->key+100);
4204                         aopPut(AOP(result),"a",2);
4205                 }
4206                 emitcode("pop","acc");
4207                 if (AOP_SIZE(result) >= 4) {
4208                         lbl = newiTempLabel(NULL);      
4209                         emitcode("jnb","F0,%05d$",lbl->key+100);
4210                         emitcode("cpl","a");
4211                         emitcode("addc","a,#0");                        
4212                         emitcode("","%05d$:", lbl->key+100);
4213                         aopPut(AOP(result),"a",3);
4214                 }
4215                 if (AOP_TYPE(result) == AOP_ACC)
4216                 {
4217                     /* We stashed the result away above. */
4218                     emitcode("mov", "acc,%s", DP2_RESULT_REG);
4219                 }           
4220                 
4221         }
4222         freeAsmop (result, NULL, ic, TRUE);
4223         return ;
4224 }
4225
4226 /*-----------------------------------------------------------------*/
4227 /* genMult - generates code for multiplication                     */
4228 /*-----------------------------------------------------------------*/
4229 static void
4230 genMult (iCode * ic)
4231 {
4232   operand *left = IC_LEFT (ic);
4233   operand *right = IC_RIGHT (ic);
4234   operand *result = IC_RESULT (ic);
4235
4236   D (emitcode (";", "genMult "););
4237
4238   /* assign the amsops */
4239   AOP_OP_2 (ic);
4240
4241   /* special cases first */
4242   /* both are bits */
4243   if (AOP_TYPE (left) == AOP_CRY &&
4244       AOP_TYPE (right) == AOP_CRY)
4245     {
4246       genMultbits (left, right, result, ic);
4247       goto release;
4248     }
4249
4250   /* if both are of size == 1 */
4251   if (AOP_SIZE (left) == 1 &&
4252       AOP_SIZE (right) == 1)
4253     {
4254       genMultOneByte (left, right, result, ic);
4255       goto release;
4256     }
4257
4258   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4259           /* use the ds390 ARITHMETIC accel UNIT */
4260           genMultTwoByte (left, right, result, ic);
4261           return ;
4262   }
4263   /* should have been converted to function call */
4264   assert (0);
4265
4266 release:
4267   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4268   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4269   freeAsmop (result, NULL, ic, TRUE);
4270 }
4271
4272 /*-----------------------------------------------------------------*/
4273 /* genDivbits :- division of bits                                  */
4274 /*-----------------------------------------------------------------*/
4275 static void
4276 genDivbits (operand * left,
4277             operand * right,
4278             operand * result,
4279             iCode   * ic)
4280 {
4281
4282   char *l;
4283
4284   /* the result must be bit */
4285   LOAD_AB_FOR_DIV (left, right, l);
4286   emitcode ("div", "ab");
4287   emitcode ("rrc", "a");
4288   aopOp(result, ic, TRUE, FALSE);
4289     
4290   aopPut (AOP (result), "c", 0);
4291 }
4292
4293 /*-----------------------------------------------------------------*/
4294 /* genDivOneByte : 8 bit division                                  */
4295 /*-----------------------------------------------------------------*/
4296 static void
4297 genDivOneByte (operand * left,
4298                operand * right,
4299                operand * result,
4300                iCode   * ic)
4301 {
4302   sym_link *opetype = operandType (result);
4303   char *l;
4304   symbol *lbl;
4305   int size, offset;
4306
4307   offset = 1;
4308   /* signed or unsigned */
4309   if (SPEC_USIGN (opetype))
4310     {
4311         /* unsigned is easy */
4312         LOAD_AB_FOR_DIV (left, right, l);
4313         emitcode ("div", "ab");
4314
4315         _G.accInUse++;
4316         aopOp(result, ic, TRUE, FALSE);
4317         aopPut (AOP (result), "a", 0);
4318         _G.accInUse--;
4319
4320         size = AOP_SIZE (result) - 1;
4321         
4322         while (size--)
4323         {
4324             aopPut (AOP (result), zero, offset++);
4325         }
4326       return;
4327     }
4328
4329   /* signed is a little bit more difficult */
4330
4331   /* save the signs of the operands */
4332   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4333   MOVA (l);
4334   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4335   emitcode ("push", "acc");     /* save it on the stack */
4336
4337   /* now sign adjust for both left & right */
4338   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4339   MOVA (l);
4340   lbl = newiTempLabel (NULL);
4341   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4342   emitcode ("cpl", "a");
4343   emitcode ("inc", "a");
4344   emitcode ("", "%05d$:", (lbl->key + 100));
4345   emitcode ("mov", "b,a");
4346
4347   /* sign adjust left side */
4348   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4349   MOVA (l);
4350
4351   lbl = newiTempLabel (NULL);
4352   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4353   emitcode ("cpl", "a");
4354   emitcode ("inc", "a");
4355   emitcode ("", "%05d$:", (lbl->key + 100));
4356
4357   /* now the division */
4358   emitcode ("nop", "; workaround for DS80C390 div bug.");
4359   emitcode ("div", "ab");
4360   /* we are interested in the lower order
4361      only */
4362   emitcode ("mov", "b,a");
4363   lbl = newiTempLabel (NULL);
4364   emitcode ("pop", "acc");
4365   /* if there was an over flow we don't
4366      adjust the sign of the result */
4367   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4368   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4369   CLRC;
4370   emitcode ("clr", "a");
4371   emitcode ("subb", "a,b");
4372   emitcode ("mov", "b,a");
4373   emitcode ("", "%05d$:", (lbl->key + 100));
4374
4375   /* now we are done */
4376     _G.accInUse++;
4377     aopOp(result, ic, TRUE, FALSE);
4378     
4379     aopPut (AOP (result), "b", 0);
4380     
4381     size = AOP_SIZE (result) - 1;
4382     
4383     if (size > 0)
4384     {
4385       emitcode ("mov", "c,b.7");
4386       emitcode ("subb", "a,acc");
4387     }
4388     while (size--)
4389     {
4390         aopPut (AOP (result), "a", offset++);
4391     }
4392     _G.accInUse--;
4393
4394 }
4395
4396 /*-----------------------------------------------------------------*/
4397 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4398 /*-----------------------------------------------------------------*/
4399 static void genDivTwoByte (operand *left, operand *right, 
4400                             operand *result, iCode *ic)
4401 {
4402         sym_link *retype = getSpec(operandType(right));
4403         sym_link *letype = getSpec(operandType(left));
4404         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4405         symbol *lbl;
4406
4407         /* load up MA with left */
4408         if (!umult) {
4409                 emitcode("clr","F0");
4410                 lbl = newiTempLabel(NULL);
4411                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4412                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4413                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4414                 emitcode ("xch", "a,b");
4415                 emitcode ("cpl","a");
4416                 emitcode ("add", "a,#1");
4417                 emitcode ("xch", "a,b");
4418                 emitcode ("cpl", "a"); // msb
4419                 emitcode ("addc","a,#0");
4420                 emitcode ("setb","F0");
4421                 emitcode ("","%05d$:",lbl->key+100);
4422                 emitcode ("mov","ma,b");
4423                 emitcode ("mov","ma,a");
4424         } else {
4425                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4426                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4427         }
4428
4429         /* load up MB with right */
4430         if (!umult) {
4431                 if (AOP_TYPE(right) == AOP_LIT) {
4432                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4433                         if (val < 0) {
4434                                 lbl = newiTempLabel(NULL);
4435                                 emitcode ("jbc","F0,%05d$",lbl->key+100);
4436                                 emitcode("setb","F0");
4437                                 emitcode ("","%05d$:",lbl->key+100);
4438                                 val = -val;
4439                         } 
4440                         emitcode ("mov","mb,#0x%02x",val & 0xff);                   
4441                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4442                 } else {
4443                         lbl = newiTempLabel(NULL);
4444                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4445                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4446                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4447                         emitcode ("xch", "a,b");
4448                         emitcode ("cpl","a");
4449                         emitcode ("add", "a,#1");
4450                         emitcode ("xch", "a,b");
4451                         emitcode ("cpl", "a"); // msb
4452                         emitcode ("addc", "a,#0");
4453                         emitcode ("jbc","F0,%05d$",lbl->key+100);
4454                         emitcode ("setb","F0");
4455                         emitcode ("","%05d$:",lbl->key+100);
4456                         emitcode ("mov","mb,b");
4457                         emitcode ("mov","mb,a");
4458                 }
4459         } else {
4460                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4461                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4462         }
4463
4464         /* wait for multiplication to finish */
4465         lbl = newiTempLabel(NULL);
4466         emitcode("","%05d$:", lbl->key+100);
4467         emitcode("mov","a,mcnt1");
4468         emitcode("anl","a,#0x80");
4469         emitcode("jnz","%05d$",lbl->key+100);
4470         
4471         freeAsmop (left, NULL, ic, TRUE);
4472         freeAsmop (right, NULL, ic,TRUE);
4473         aopOp(result, ic, TRUE, FALSE);
4474
4475         /* if unsigned then simple */   
4476         if (umult) {
4477                 aopPut(AOP(result),"ma",1);
4478                 aopPut(AOP(result),"ma",0);
4479         } else {
4480                 emitcode("push","ma");
4481                 MOVA("ma");
4482                 /* negate result if needed */
4483                 lbl = newiTempLabel(NULL);      
4484                 emitcode("jnb","F0,%05d$",lbl->key+100);
4485                 emitcode("cpl","a");
4486                 emitcode("add","a,#1");
4487                 emitcode("","%05d$:", lbl->key+100);
4488                 aopPut(AOP(result),"a",0);
4489                 emitcode("pop","acc");
4490                 lbl = newiTempLabel(NULL);      
4491                 emitcode("jnb","F0,%05d$",lbl->key+100);
4492                 emitcode("cpl","a");
4493                 emitcode("addc","a,#0");
4494                 emitcode("","%05d$:", lbl->key+100);
4495                 aopPut(AOP(result),"a",1);
4496         }
4497         freeAsmop (result, NULL, ic, TRUE);
4498         return ;
4499 }
4500
4501 /*-----------------------------------------------------------------*/
4502 /* genDiv - generates code for division                            */
4503 /*-----------------------------------------------------------------*/
4504 static void
4505 genDiv (iCode * ic)
4506 {
4507   operand *left = IC_LEFT (ic);
4508   operand *right = IC_RIGHT (ic);
4509   operand *result = IC_RESULT (ic);
4510
4511   D (emitcode (";", "genDiv "););
4512
4513   /* assign the amsops */
4514   AOP_OP_2 (ic);
4515
4516   /* special cases first */
4517   /* both are bits */
4518   if (AOP_TYPE (left) == AOP_CRY &&
4519       AOP_TYPE (right) == AOP_CRY)
4520     {
4521       genDivbits (left, right, result, ic);
4522       goto release;
4523     }
4524
4525   /* if both are of size == 1 */
4526   if (AOP_SIZE (left) == 1 &&
4527       AOP_SIZE (right) == 1)
4528     {
4529       genDivOneByte (left, right, result, ic);
4530       goto release;
4531     }
4532
4533   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4534           /* use the ds390 ARITHMETIC accel UNIT */
4535           genDivTwoByte (left, right, result, ic);
4536           return ;
4537   }
4538   /* should have been converted to function call */
4539   assert (0);
4540 release:
4541   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4542   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4543   freeAsmop (result, NULL, ic, TRUE);
4544 }
4545
4546 /*-----------------------------------------------------------------*/
4547 /* genModbits :- modulus of bits                                   */
4548 /*-----------------------------------------------------------------*/
4549 static void
4550 genModbits (operand * left,
4551             operand * right,
4552             operand * result,
4553             iCode   * ic)
4554 {
4555
4556   char *l;
4557
4558   /* the result must be bit */
4559   LOAD_AB_FOR_DIV (left, right, l);
4560   emitcode ("div", "ab");
4561   emitcode ("mov", "a,b");
4562   emitcode ("rrc", "a");
4563   aopOp(result, ic, TRUE, FALSE);
4564   aopPut (AOP (result), "c", 0);
4565 }
4566
4567 /*-----------------------------------------------------------------*/
4568 /* genModOneByte : 8 bit modulus                                   */
4569 /*-----------------------------------------------------------------*/
4570 static void
4571 genModOneByte (operand * left,
4572                operand * right,
4573                operand * result,
4574                iCode   * ic)
4575 {
4576   sym_link *opetype = operandType (result);
4577   char *l;
4578   symbol *lbl;
4579
4580   /* signed or unsigned */
4581   if (SPEC_USIGN (opetype))
4582     {
4583       /* unsigned is easy */
4584       LOAD_AB_FOR_DIV (left, right, l);
4585       emitcode ("div", "ab");
4586       aopOp(result, ic, TRUE, FALSE);   
4587       aopPut (AOP (result), "b", 0);
4588       return;
4589     }
4590
4591   /* signed is a little bit more difficult */
4592
4593   /* save the signs of the operands */
4594   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4595   MOVA (l);
4596
4597   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4598   emitcode ("push", "acc");     /* save it on the stack */
4599
4600   /* now sign adjust for both left & right */
4601   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4602   MOVA (l);
4603
4604   lbl = newiTempLabel (NULL);
4605   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4606   emitcode ("cpl", "a");
4607   emitcode ("inc", "a");
4608   emitcode ("", "%05d$:", (lbl->key + 100));
4609   emitcode ("mov", "b,a");
4610
4611   /* sign adjust left side */
4612   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4613   MOVA (l);
4614
4615   lbl = newiTempLabel (NULL);
4616   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4617   emitcode ("cpl", "a");
4618   emitcode ("inc", "a");
4619   emitcode ("", "%05d$:", (lbl->key + 100));
4620
4621   /* now the multiplication */
4622   emitcode ("nop", "; workaround for DS80C390 div bug.");
4623   emitcode ("div", "ab");
4624   /* we are interested in the lower order
4625      only */
4626   lbl = newiTempLabel (NULL);
4627   emitcode ("pop", "acc");
4628   /* if there was an over flow we don't
4629      adjust the sign of the result */
4630   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4631   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4632   CLRC;
4633   emitcode ("clr", "a");
4634   emitcode ("subb", "a,b");
4635   emitcode ("mov", "b,a");
4636   emitcode ("", "%05d$:", (lbl->key + 100));
4637
4638   /* now we are done */
4639   aopOp(result, ic, TRUE, FALSE);    
4640   aopPut (AOP (result), "b", 0);
4641
4642 }
4643
4644 /*-----------------------------------------------------------------*/
4645 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4646 /*-----------------------------------------------------------------*/
4647 static void genModTwoByte (operand *left, operand *right, 
4648                             operand *result, iCode *ic)
4649 {
4650         sym_link *retype = getSpec(operandType(right));
4651         sym_link *letype = getSpec(operandType(left));
4652         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4653         symbol *lbl;
4654
4655         /* load up MA with left */
4656         if (!umult) {
4657                 lbl = newiTempLabel(NULL);
4658                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4659                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4660                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4661                 emitcode ("xch", "a,b");
4662                 emitcode ("cpl","a");
4663                 emitcode ("add", "a,#1");
4664                 emitcode ("xch", "a,b");
4665                 emitcode ("cpl", "a"); // msb
4666                 emitcode ("addc","a,#0");
4667                 emitcode ("","%05d$:",lbl->key+100);
4668                 emitcode ("mov","ma,b");
4669                 emitcode ("mov","ma,a");
4670         } else {
4671                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4672                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4673         }
4674
4675         /* load up MB with right */
4676         if (!umult) {
4677                 if (AOP_TYPE(right) == AOP_LIT) {
4678                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4679                         if (val < 0) {
4680                                 val = -val;
4681                         } 
4682                         emitcode ("mov","mb,#0x%02x",val & 0xff);
4683                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);                    
4684                 } else {
4685                         lbl = newiTempLabel(NULL);
4686                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4687                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4688                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4689                         emitcode ("xch", "a,b");
4690                         emitcode ("cpl","a");
4691                         emitcode ("add", "a,#1");
4692                         emitcode ("xch", "a,b");
4693                         emitcode ("cpl", "a"); // msb
4694                         emitcode ("addc", "a,#0");
4695                         emitcode ("","%05d$:",lbl->key+100);
4696                         emitcode ("mov","mb,b");
4697                         emitcode ("mov","mb,a");
4698                 }
4699         } else {
4700                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4701                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4702         }
4703
4704         /* wait for multiplication to finish */
4705         lbl = newiTempLabel(NULL);
4706         emitcode("","%05d$:", lbl->key+100);
4707         emitcode("mov","a,mcnt1");
4708         emitcode("anl","a,#0x80");
4709         emitcode("jnz","%05d$",lbl->key+100);
4710         
4711         freeAsmop (left, NULL, ic, TRUE);
4712         freeAsmop (right, NULL, ic,TRUE);
4713         aopOp(result, ic, TRUE, FALSE);
4714
4715         aopPut(AOP(result),"mb",1);
4716         aopPut(AOP(result),"mb",0);
4717         freeAsmop (result, NULL, ic, TRUE);
4718         return ;
4719 }
4720
4721 /*-----------------------------------------------------------------*/
4722 /* genMod - generates code for division                            */
4723 /*-----------------------------------------------------------------*/
4724 static void
4725 genMod (iCode * ic)
4726 {
4727   operand *left = IC_LEFT (ic);
4728   operand *right = IC_RIGHT (ic);
4729   operand *result = IC_RESULT (ic);
4730
4731   D (emitcode (";", "genMod "); );
4732
4733   /* assign the amsops */
4734   AOP_OP_2 (ic);
4735
4736   /* special cases first */
4737   /* both are bits */
4738   if (AOP_TYPE (left) == AOP_CRY &&
4739       AOP_TYPE (right) == AOP_CRY)
4740     {
4741       genModbits (left, right, result, ic);
4742       goto release;
4743     }
4744
4745   /* if both are of size == 1 */
4746   if (AOP_SIZE (left) == 1 &&
4747       AOP_SIZE (right) == 1)
4748     {
4749       genModOneByte (left, right, result, ic);
4750       goto release;
4751     }
4752
4753   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4754           /* use the ds390 ARITHMETIC accel UNIT */
4755           genModTwoByte (left, right, result, ic);
4756           return ;
4757   }
4758
4759   /* should have been converted to function call */
4760   assert (0);
4761
4762 release:
4763   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4764   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4765   freeAsmop (result, NULL, ic, TRUE);
4766 }
4767
4768 /*-----------------------------------------------------------------*/
4769 /* genIfxJump :- will create a jump depending on the ifx           */
4770 /*-----------------------------------------------------------------*/
4771 static void
4772 genIfxJump (iCode * ic, char *jval)
4773 {
4774   symbol *jlbl;
4775   symbol *tlbl = newiTempLabel (NULL);
4776   char *inst;
4777
4778   D (emitcode (";", "genIfxJump ");
4779     );
4780
4781   /* if true label then we jump if condition
4782      supplied is true */
4783   if (IC_TRUE (ic))
4784     {
4785       jlbl = IC_TRUE (ic);
4786       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4787                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4788     }
4789   else
4790     {
4791       /* false label is present */
4792       jlbl = IC_FALSE (ic);
4793       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4794                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4795     }
4796   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4797     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4798   else
4799     emitcode (inst, "%05d$", tlbl->key + 100);
4800   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4801   emitcode ("", "%05d$:", tlbl->key + 100);
4802
4803   /* mark the icode as generated */
4804   ic->generated = 1;
4805 }
4806
4807 /*-----------------------------------------------------------------*/
4808 /* genCmp :- greater or less than comparison                       */
4809 /*-----------------------------------------------------------------*/
4810 static void
4811 genCmp (operand * left, operand * right,
4812         iCode * ic, iCode * ifx, int sign)
4813 {
4814   int size, offset = 0;
4815   unsigned long lit = 0L;
4816   operand *result;
4817
4818   D (emitcode (";", "genCmp");
4819     );
4820
4821   result = IC_RESULT (ic);
4822
4823   /* if left & right are bit variables */
4824   if (AOP_TYPE (left) == AOP_CRY &&
4825       AOP_TYPE (right) == AOP_CRY)
4826     {
4827       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4828       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4829     }
4830   else
4831     {
4832       /* subtract right from left if at the
4833          end the carry flag is set then we know that
4834          left is greater than right */
4835       size = max (AOP_SIZE (left), AOP_SIZE (right));
4836
4837       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4838       if ((size == 1) && !sign &&
4839           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4840         {
4841           symbol *lbl = newiTempLabel (NULL);
4842           emitcode ("cjne", "%s,%s,%05d$",
4843                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4844                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4845                     lbl->key + 100);
4846           emitcode ("", "%05d$:", lbl->key + 100);
4847         }
4848       else
4849         {
4850           if (AOP_TYPE (right) == AOP_LIT)
4851             {
4852               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4853               /* optimize if(x < 0) or if(x >= 0) */
4854               if (lit == 0L)
4855                 {
4856                   if (!sign)
4857                     {
4858                       CLRC;
4859                     }
4860                   else
4861                     {
4862                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4863
4864                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4865                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4866
4867                       aopOp (result, ic, FALSE, FALSE);
4868
4869                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4870                         {
4871                           freeAsmop (result, NULL, ic, TRUE);
4872                           genIfxJump (ifx, "acc.7");
4873                           return;
4874                         }
4875                       else
4876                         {
4877                           emitcode ("rlc", "a");
4878                         }
4879                       goto release_freedLR;
4880                     }
4881                   goto release;
4882                 }
4883             }
4884           CLRC;
4885           while (size--)
4886             {
4887               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4888               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4889               emitcode (";", "genCmp #2");
4890               if (sign && (size == 0))
4891                 {
4892                   emitcode (";", "genCmp #3");
4893                   emitcode ("xrl", "a,#0x80");
4894                   if (AOP_TYPE (right) == AOP_LIT)
4895                     {
4896                       unsigned long lit = (unsigned long)
4897                       floatFromVal (AOP (right)->aopu.aop_lit);
4898                       emitcode (";", "genCmp #3.1");
4899                       emitcode ("subb", "a,#0x%02x",
4900                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4901                     }
4902                   else
4903                     {
4904                       emitcode (";", "genCmp #3.2");
4905                       if (AOP_NEEDSACC (right))
4906                         {
4907                           emitcode ("push", "acc");
4908                         }
4909                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4910                                                        FALSE, FALSE, FALSE));
4911                       emitcode ("xrl", "b,#0x80");
4912                       if (AOP_NEEDSACC (right))
4913                         {
4914                           emitcode ("pop", "acc");
4915                         }
4916                       emitcode ("subb", "a,b");
4917                     }
4918                 }
4919               else
4920                 {
4921                   const char *s;
4922
4923                   emitcode (";", "genCmp #4");
4924                   if (AOP_NEEDSACC (right))
4925                     {
4926                       /* Yuck!! */
4927                       emitcode (";", "genCmp #4.1");
4928                       emitcode ("xch", "a, b");
4929                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4930                       emitcode ("xch", "a, b");
4931                       s = "b";
4932                     }
4933                   else
4934                     {
4935                       emitcode (";", "genCmp #4.2");
4936                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4937                     }
4938
4939                   emitcode ("subb", "a,%s", s);
4940                 }
4941             }
4942         }
4943     }
4944
4945 release:
4946 /* Don't need the left & right operands any more; do need the result. */
4947   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4948   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4949
4950   aopOp (result, ic, FALSE, FALSE);
4951
4952 release_freedLR:
4953
4954   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4955     {
4956       outBitC (result);
4957     }
4958   else
4959     {
4960       /* if the result is used in the next
4961          ifx conditional branch then generate
4962          code a little differently */
4963       if (ifx)
4964         {
4965           genIfxJump (ifx, "c");
4966         }
4967       else
4968         {
4969           outBitC (result);
4970         }
4971       /* leave the result in acc */
4972     }
4973   freeAsmop (result, NULL, ic, TRUE);
4974 }
4975
4976 /*-----------------------------------------------------------------*/
4977 /* genCmpGt :- greater than comparison                             */
4978 /*-----------------------------------------------------------------*/
4979 static void
4980 genCmpGt (iCode * ic, iCode * ifx)
4981 {
4982   operand *left, *right;
4983   sym_link *letype, *retype;
4984   int sign;
4985
4986   D (emitcode (";", "genCmpGt ");
4987     );
4988
4989   left = IC_LEFT (ic);
4990   right = IC_RIGHT (ic);
4991
4992   letype = getSpec (operandType (left));
4993   retype = getSpec (operandType (right));
4994   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4995
4996   /* assign the left & right amsops */
4997   AOP_OP_2 (ic);
4998
4999   genCmp (right, left, ic, ifx, sign);
5000 }
5001
5002 /*-----------------------------------------------------------------*/
5003 /* genCmpLt - less than comparisons                                */
5004 /*-----------------------------------------------------------------*/
5005 static void
5006 genCmpLt (iCode * ic, iCode * ifx)
5007 {
5008   operand *left, *right;
5009   sym_link *letype, *retype;
5010   int sign;
5011
5012   D (emitcode (";", "genCmpLt "););
5013
5014   left = IC_LEFT (ic);
5015   right = IC_RIGHT (ic);
5016
5017   letype = getSpec (operandType (left));
5018   retype = getSpec (operandType (right));
5019   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5020
5021   /* assign the left & right amsops */
5022   AOP_OP_2 (ic);
5023
5024   genCmp (left, right, ic, ifx, sign);
5025 }
5026
5027 /*-----------------------------------------------------------------*/
5028 /* gencjneshort - compare and jump if not equal                    */
5029 /*-----------------------------------------------------------------*/
5030 static void
5031 gencjneshort (operand * left, operand * right, symbol * lbl)
5032 {
5033   int size = max (AOP_SIZE (left), AOP_SIZE (right));
5034   int offset = 0;
5035   unsigned long lit = 0L;
5036
5037   D (emitcode (";", "gencjneshort");
5038     );
5039
5040   /* if the left side is a literal or
5041      if the right is in a pointer register and left
5042      is not */
5043   if ((AOP_TYPE (left) == AOP_LIT) ||
5044       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5045     {
5046       operand *t = right;
5047       right = left;
5048       left = t;
5049     }
5050
5051   if (AOP_TYPE (right) == AOP_LIT)
5052     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5053
5054   if (opIsGptr (left) || opIsGptr (right))
5055     {
5056       /* We are comparing a generic pointer to something.
5057        * Exclude the generic type byte from the comparison.
5058        */
5059       size--;
5060       D (emitcode (";", "cjneshort: generic ptr special case.");
5061         )
5062     }
5063
5064
5065   /* if the right side is a literal then anything goes */
5066   if (AOP_TYPE (right) == AOP_LIT &&
5067       AOP_TYPE (left) != AOP_DIR)
5068     {
5069       while (size--)
5070         {
5071           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5072           MOVA (l);
5073           emitcode ("cjne", "a,%s,%05d$",
5074                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5075                     lbl->key + 100);
5076           offset++;
5077         }
5078     }
5079
5080   /* if the right side is in a register or in direct space or
5081      if the left is a pointer register & right is not */
5082   else if (AOP_TYPE (right) == AOP_REG ||
5083            AOP_TYPE (right) == AOP_DIR ||
5084            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5085            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5086     {
5087       while (size--)
5088         {
5089           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5090           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5091               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5092             emitcode ("jnz", "%05d$", lbl->key + 100);
5093           else
5094             emitcode ("cjne", "a,%s,%05d$",
5095                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5096                       lbl->key + 100);
5097           offset++;
5098         }
5099     }
5100   else
5101     {
5102       /* right is a pointer reg need both a & b */
5103       while (size--)
5104         {
5105           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5106           if (strcmp (l, "b"))
5107             emitcode ("mov", "b,%s", l);
5108           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5109           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5110           offset++;
5111         }
5112     }
5113 }
5114
5115 /*-----------------------------------------------------------------*/
5116 /* gencjne - compare and jump if not equal                         */
5117 /*-----------------------------------------------------------------*/
5118 static void
5119 gencjne (operand * left, operand * right, symbol * lbl)
5120 {
5121   symbol *tlbl = newiTempLabel (NULL);
5122
5123   D (emitcode (";", "gencjne");
5124     );
5125
5126   gencjneshort (left, right, lbl);
5127
5128   emitcode ("mov", "a,%s", one);
5129   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5130   emitcode ("", "%05d$:", lbl->key + 100);
5131   emitcode ("clr", "a");
5132   emitcode ("", "%05d$:", tlbl->key + 100);
5133 }
5134
5135 /*-----------------------------------------------------------------*/
5136 /* genCmpEq - generates code for equal to                          */
5137 /*-----------------------------------------------------------------*/
5138 static void
5139 genCmpEq (iCode * ic, iCode * ifx)
5140 {
5141   operand *left, *right, *result;
5142
5143   D (emitcode (";", "genCmpEq ");
5144     );
5145
5146   AOP_OP_2 (ic);
5147   AOP_SET_LOCALS (ic);
5148
5149   /* if literal, literal on the right or
5150      if the right is in a pointer register and left
5151      is not */
5152   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5153       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5154     {
5155       operand *t = IC_RIGHT (ic);
5156       IC_RIGHT (ic) = IC_LEFT (ic);
5157       IC_LEFT (ic) = t;
5158     }
5159
5160   if (ifx &&                    /* !AOP_SIZE(result) */
5161       OP_SYMBOL (result) &&
5162       OP_SYMBOL (result)->regType == REG_CND)
5163     {
5164       symbol *tlbl;
5165       /* if they are both bit variables */
5166       if (AOP_TYPE (left) == AOP_CRY &&
5167           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5168         {
5169           if (AOP_TYPE (right) == AOP_LIT)
5170             {
5171               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5172               if (lit == 0L)
5173                 {
5174                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5175                   emitcode ("cpl", "c");
5176                 }
5177               else if (lit == 1L)
5178                 {
5179                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5180                 }
5181               else
5182                 {
5183                   emitcode ("clr", "c");
5184                 }
5185               /* AOP_TYPE(right) == AOP_CRY */
5186             }
5187           else
5188             {
5189               symbol *lbl = newiTempLabel (NULL);
5190               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5191               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5192               emitcode ("cpl", "c");
5193               emitcode ("", "%05d$:", (lbl->key + 100));
5194             }
5195           /* if true label then we jump if condition
5196              supplied is true */
5197           tlbl = newiTempLabel (NULL);
5198           if (IC_TRUE (ifx))
5199             {
5200               emitcode ("jnc", "%05d$", tlbl->key + 100);
5201               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5202             }
5203           else
5204             {
5205               emitcode ("jc", "%05d$", tlbl->key + 100);
5206               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5207             }
5208           emitcode ("", "%05d$:", tlbl->key + 100);
5209         }
5210       else
5211         {
5212           tlbl = newiTempLabel (NULL);
5213           gencjneshort (left, right, tlbl);
5214           if (IC_TRUE (ifx))
5215             {
5216               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5217               emitcode ("", "%05d$:", tlbl->key + 100);
5218             }
5219           else
5220             {
5221               symbol *lbl = newiTempLabel (NULL);
5222               emitcode ("sjmp", "%05d$", lbl->key + 100);
5223               emitcode ("", "%05d$:", tlbl->key + 100);
5224               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5225               emitcode ("", "%05d$:", lbl->key + 100);
5226             }
5227         }
5228       /* mark the icode as generated */
5229       ifx->generated = 1;
5230
5231       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5232       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5233       return;
5234     }
5235
5236   /* if they are both bit variables */
5237   if (AOP_TYPE (left) == AOP_CRY &&
5238       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5239     {
5240       if (AOP_TYPE (right) == AOP_LIT)
5241         {
5242           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5243           if (lit == 0L)
5244             {
5245               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5246               emitcode ("cpl", "c");
5247             }
5248           else if (lit == 1L)
5249             {
5250               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5251             }
5252           else
5253             {
5254               emitcode ("clr", "c");
5255             }
5256           /* AOP_TYPE(right) == AOP_CRY */
5257         }
5258       else
5259         {
5260           symbol *lbl = newiTempLabel (NULL);
5261           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5262           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5263           emitcode ("cpl", "c");
5264           emitcode ("", "%05d$:", (lbl->key + 100));
5265         }
5266
5267       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5268       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5269
5270       aopOp (result, ic, TRUE, FALSE);
5271
5272       /* c = 1 if egal */
5273       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5274         {
5275           outBitC (result);
5276           goto release;
5277         }
5278       if (ifx)
5279         {
5280           genIfxJump (ifx, "c");
5281           goto release;
5282         }
5283       /* if the result is used in an arithmetic operation
5284          then put the result in place */
5285       outBitC (result);
5286     }
5287   else
5288     {
5289       gencjne (left, right, newiTempLabel (NULL));
5290
5291       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5292       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5293
5294       aopOp (result, ic, TRUE, FALSE);
5295
5296       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5297         {
5298           aopPut (AOP (result), "a", 0);
5299           goto release;
5300         }
5301       if (ifx)
5302         {
5303           genIfxJump (ifx, "a");
5304           goto release;
5305         }
5306       /* if the result is used in an arithmetic operation
5307          then put the result in place */
5308       if (AOP_TYPE (result) != AOP_CRY)
5309         outAcc (result);
5310       /* leave the result in acc */
5311     }
5312
5313 release:
5314   freeAsmop (result, NULL, ic, TRUE);
5315 }
5316
5317 /*-----------------------------------------------------------------*/
5318 /* ifxForOp - returns the icode containing the ifx for operand     */
5319 /*-----------------------------------------------------------------*/
5320 static iCode *
5321 ifxForOp (operand * op, iCode * ic)
5322 {
5323   /* if true symbol then needs to be assigned */
5324   if (IS_TRUE_SYMOP (op))
5325     return NULL;
5326
5327   /* if this has register type condition and
5328      the next instruction is ifx with the same operand
5329      and live to of the operand is upto the ifx only then */
5330   if (ic->next &&
5331       ic->next->op == IFX &&
5332       IC_COND (ic->next)->key == op->key &&
5333       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5334     return ic->next;
5335
5336   return NULL;
5337 }
5338 /*-----------------------------------------------------------------*/
5339 /* genAndOp - for && operation                                     */
5340 /*-----------------------------------------------------------------*/
5341 static void
5342 genAndOp (iCode * ic)
5343 {
5344   operand *left, *right, *result;
5345   symbol *tlbl;
5346
5347   D (emitcode (";", "genAndOp "););
5348
5349   /* note here that && operations that are in an
5350      if statement are taken away by backPatchLabels
5351      only those used in arthmetic operations remain */
5352   AOP_OP_2 (ic);
5353   AOP_SET_LOCALS (ic);
5354
5355   /* if both are bit variables */
5356   if (AOP_TYPE (left) == AOP_CRY &&
5357       AOP_TYPE (right) == AOP_CRY)
5358     {
5359       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5360       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5361       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5362       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5363   
5364       aopOp (result,ic,FALSE, FALSE);
5365       outBitC (result);
5366     }
5367   else
5368     {
5369       tlbl = newiTempLabel (NULL);
5370       toBoolean (left);
5371       emitcode ("jz", "%05d$", tlbl->key + 100);
5372       toBoolean (right);
5373       emitcode ("", "%05d$:", tlbl->key + 100);
5374       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5375       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5376   
5377       aopOp (result,ic,FALSE, FALSE);
5378       outBitAcc (result);
5379     }
5380     freeAsmop (result, NULL, ic, TRUE);
5381 }
5382
5383
5384 /*-----------------------------------------------------------------*/
5385 /* genOrOp - for || operation                                      */
5386 /*-----------------------------------------------------------------*/
5387 static void
5388 genOrOp (iCode * ic)
5389 {
5390   operand *left, *right, *result;
5391   symbol *tlbl;
5392
5393   D (emitcode (";", "genOrOp "););
5394
5395   /* note here that || operations that are in an
5396      if statement are taken away by backPatchLabels
5397      only those used in arthmetic operations remain */
5398   AOP_OP_2 (ic);
5399   AOP_SET_LOCALS (ic);
5400
5401   /* if both are bit variables */
5402   if (AOP_TYPE (left) == AOP_CRY &&
5403       AOP_TYPE (right) == AOP_CRY)
5404     {
5405       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5406       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5407       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5408       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5409   
5410       aopOp (result,ic,FALSE, FALSE);
5411       
5412       outBitC (result);
5413     }
5414   else
5415     {
5416       tlbl = newiTempLabel (NULL);
5417       toBoolean (left);
5418       emitcode ("jnz", "%05d$", tlbl->key + 100);
5419       toBoolean (right);
5420       emitcode ("", "%05d$:", tlbl->key + 100);
5421       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5422       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5423   
5424       aopOp (result,ic,FALSE, FALSE);
5425       
5426       outBitAcc (result);
5427     }
5428
5429   freeAsmop (result, NULL, ic, TRUE);
5430 }
5431
5432 /*-----------------------------------------------------------------*/
5433 /* isLiteralBit - test if lit == 2^n                               */
5434 /*-----------------------------------------------------------------*/
5435 static int
5436 isLiteralBit (unsigned long lit)
5437 {
5438   unsigned long pw[32] =
5439   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5440    0x100L, 0x200L, 0x400L, 0x800L,
5441    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5442    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5443    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5444    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5445    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5446   int idx;
5447
5448   for (idx = 0; idx < 32; idx++)
5449     if (lit == pw[idx])
5450       return idx + 1;
5451   return 0;
5452 }
5453
5454 /*-----------------------------------------------------------------*/
5455 /* continueIfTrue -                                                */
5456 /*-----------------------------------------------------------------*/
5457 static void
5458 continueIfTrue (iCode * ic)
5459 {
5460   if (IC_TRUE (ic))
5461     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5462   ic->generated = 1;
5463 }
5464
5465 /*-----------------------------------------------------------------*/
5466 /* jmpIfTrue -                                                     */
5467 /*-----------------------------------------------------------------*/
5468 static void
5469 jumpIfTrue (iCode * ic)
5470 {
5471   if (!IC_TRUE (ic))
5472     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5473   ic->generated = 1;
5474 }
5475
5476 /*-----------------------------------------------------------------*/
5477 /* jmpTrueOrFalse -                                                */
5478 /*-----------------------------------------------------------------*/
5479 static void
5480 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5481 {
5482   // ugly but optimized by peephole
5483   if (IC_TRUE (ic))
5484     {
5485       symbol *nlbl = newiTempLabel (NULL);
5486       emitcode ("sjmp", "%05d$", nlbl->key + 100);
5487       emitcode ("", "%05d$:", tlbl->key + 100);
5488       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5489       emitcode ("", "%05d$:", nlbl->key + 100);
5490     }
5491   else
5492     {
5493       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5494       emitcode ("", "%05d$:", tlbl->key + 100);
5495     }
5496   ic->generated = 1;
5497 }
5498
5499 // Generate code to perform a bit-wise logic operation
5500 // on two operands in far space (assumed to already have been 
5501 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5502 // in far space. This requires pushing the result on the stack
5503 // then popping it into the result.
5504 static void
5505 genFarFarLogicOp(iCode *ic, char *logicOp)
5506 {
5507       int size, resultSize, compSize;
5508       int offset = 0;
5509       
5510       TR_AP("#5");
5511       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5512       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5513                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5514       
5515       _startLazyDPSEvaluation();
5516       for (size = compSize; (size--); offset++)
5517       {
5518           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5519           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5520           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5521           
5522           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5523           emitcode ("push", "acc");
5524       }
5525       _endLazyDPSEvaluation();
5526      
5527       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5528       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5529       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5530      
5531       resultSize = AOP_SIZE(IC_RESULT(ic));
5532
5533       ADJUST_PUSHED_RESULT(compSize, resultSize);
5534
5535       _startLazyDPSEvaluation();
5536       while (compSize--)
5537       {
5538           emitcode ("pop", "acc");
5539           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5540       }
5541       _endLazyDPSEvaluation();
5542       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5543 }
5544
5545
5546 /*-----------------------------------------------------------------*/
5547 /* genAnd  - code for and                                          */
5548 /*-----------------------------------------------------------------*/
5549 static void
5550 genAnd (iCode * ic, iCode * ifx)
5551 {
5552   operand *left, *right, *result;
5553   int size, offset = 0;
5554   unsigned long lit = 0L;
5555   int bytelit = 0;
5556   char buffer[10];
5557   bool pushResult;
5558
5559   D (emitcode (";", "genAnd "););
5560
5561   AOP_OP_3_NOFATAL (ic, pushResult);
5562   AOP_SET_LOCALS (ic);
5563
5564   if (pushResult)
5565   {
5566       genFarFarLogicOp(ic, "anl");
5567       return;
5568   }  
5569
5570 #ifdef DEBUG_TYPE
5571   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5572             AOP_TYPE (result),
5573             AOP_TYPE (left), AOP_TYPE (right));
5574   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5575             AOP_SIZE (result),
5576             AOP_SIZE (left), AOP_SIZE (right));
5577 #endif
5578
5579   /* if left is a literal & right is not then exchange them */
5580   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5581 #ifdef LOGIC_OPS_BROKEN      
5582     ||  AOP_NEEDSACC (left)
5583 #endif
5584     )
5585     {
5586       operand *tmp = right;
5587       right = left;
5588       left = tmp;
5589     }
5590
5591   /* if result = right then exchange them */
5592   if (sameRegs (AOP (result), AOP (right)))
5593     {
5594       operand *tmp = right;
5595       right = left;
5596       left = tmp;
5597     }
5598
5599   /* if right is bit then exchange them */
5600   if (AOP_TYPE (right) == AOP_CRY &&
5601       AOP_TYPE (left) != AOP_CRY)
5602     {
5603       operand *tmp = right;
5604       right = left;
5605       left = tmp;
5606     }
5607   if (AOP_TYPE (right) == AOP_LIT)
5608     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5609
5610   size = AOP_SIZE (result);
5611
5612   // if(bit & yy)
5613   // result = bit & yy;
5614   if (AOP_TYPE (left) == AOP_CRY)
5615     {
5616       // c = bit & literal;
5617       if (AOP_TYPE (right) == AOP_LIT)
5618         {
5619           if (lit & 1)
5620             {
5621               if (size && sameRegs (AOP (result), AOP (left)))
5622                 // no change
5623                 goto release;
5624               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5625             }
5626           else
5627             {
5628               // bit(result) = 0;
5629               if (size && (AOP_TYPE (result) == AOP_CRY))
5630                 {
5631                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5632                   goto release;
5633                 }
5634               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5635                 {
5636                   jumpIfTrue (ifx);
5637                   goto release;
5638                 }
5639               emitcode ("clr", "c");
5640             }
5641         }
5642       else
5643         {
5644           if (AOP_TYPE (right) == AOP_CRY)
5645             {
5646               // c = bit & bit;
5647               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5648               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5649             }
5650           else
5651             {
5652               // c = bit & val;
5653               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5654               // c = lsb
5655               emitcode ("rrc", "a");
5656               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5657             }
5658         }
5659       // bit = c
5660       // val = c
5661       if (size)
5662         outBitC (result);
5663       // if(bit & ...)
5664       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5665         genIfxJump (ifx, "c");
5666       goto release;
5667     }
5668
5669   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5670   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5671   if ((AOP_TYPE (right) == AOP_LIT) &&
5672       (AOP_TYPE (result) == AOP_CRY) &&
5673       (AOP_TYPE (left) != AOP_CRY))
5674     {
5675       int posbit = isLiteralBit (lit);
5676       /* left &  2^n */
5677       if (posbit)
5678         {
5679           posbit--;
5680           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5681           // bit = left & 2^n
5682           if (size)
5683             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5684           // if(left &  2^n)
5685           else
5686             {
5687               if (ifx)
5688                 {
5689                   sprintf (buffer, "acc.%d", posbit & 0x07);
5690                   genIfxJump (ifx, buffer);
5691                 }
5692               goto release;
5693             }
5694         }
5695       else
5696         {
5697           symbol *tlbl = newiTempLabel (NULL);
5698           int sizel = AOP_SIZE (left);
5699           if (size)
5700             emitcode ("setb", "c");
5701           while (sizel--)
5702             {
5703               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5704                 {
5705                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5706                   // byte ==  2^n ?
5707                   if ((posbit = isLiteralBit (bytelit)) != 0)
5708                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5709                   else
5710                     {
5711                       if (bytelit != 0x0FFL)
5712                         emitcode ("anl", "a,%s",
5713                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5714                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5715                     }
5716                 }
5717               offset++;
5718             }
5719           // bit = left & literal
5720           if (size)
5721             {
5722               emitcode ("clr", "c");
5723               emitcode ("", "%05d$:", tlbl->key + 100);
5724             }
5725           // if(left & literal)
5726           else
5727             {
5728               if (ifx)
5729                 jmpTrueOrFalse (ifx, tlbl);
5730               goto release;
5731             }
5732         }
5733       outBitC (result);
5734       goto release;
5735     }
5736
5737   /* if left is same as result */
5738   if (sameRegs (AOP (result), AOP (left)))
5739     {
5740       for (; size--; offset++)
5741         {
5742           if (AOP_TYPE (right) == AOP_LIT)
5743             {
5744               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5745                 continue;
5746               else if (bytelit == 0)
5747                 aopPut (AOP (result), zero, offset);
5748               else if (IS_AOP_PREG (result))
5749                 {
5750                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5751                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5752                   aopPut (AOP (result), "a", offset);
5753                 }
5754               else
5755                 emitcode ("anl", "%s,%s",
5756                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5757                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5758             }
5759           else
5760             {
5761               if (AOP_TYPE (left) == AOP_ACC)
5762                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5763               else
5764                 {
5765                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5766                   if (IS_AOP_PREG (result))
5767                     {
5768                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5769                       aopPut (AOP (result), "a", offset);
5770
5771                     }
5772                   else
5773                     emitcode ("anl", "%s,a",
5774                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5775                 }
5776             }
5777         }
5778     }
5779   else
5780     {
5781       // left & result in different registers
5782       if (AOP_TYPE (result) == AOP_CRY)
5783         {
5784           // result = bit
5785           // if(size), result in bit
5786           // if(!size && ifx), conditional oper: if(left & right)
5787           symbol *tlbl = newiTempLabel (NULL);
5788           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5789           if (size)
5790             emitcode ("setb", "c");
5791           while (sizer--)
5792             {
5793               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5794                 emitcode ("anl", "a,%s",
5795                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5796               } else {
5797                 if (AOP_TYPE(left)==AOP_ACC) {
5798                   emitcode("mov", "b,a");
5799                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5800                   emitcode("anl", "a,b");
5801                 }else {
5802                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5803                   emitcode ("anl", "a,%s",
5804                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5805                 }
5806               }
5807               emitcode ("jnz", "%05d$", tlbl->key + 100);
5808               offset++;
5809             }
5810           if (size)
5811             {
5812               CLRC;
5813               emitcode ("", "%05d$:", tlbl->key + 100);
5814               outBitC (result);
5815             }
5816           else if (ifx)
5817             jmpTrueOrFalse (ifx, tlbl);
5818         }
5819       else
5820         {
5821           for (; (size--); offset++)
5822             {
5823               // normal case
5824               // result = left & right
5825               if (AOP_TYPE (right) == AOP_LIT)
5826                 {
5827                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5828                     {
5829                       aopPut (AOP (result),
5830                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5831                               offset);
5832                       continue;
5833                     }
5834                   else if (bytelit == 0)
5835                     {
5836                       aopPut (AOP (result), zero, offset);
5837                       continue;
5838                     }
5839                   D (emitcode (";", "better literal AND."););
5840                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5841                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5842                                                     FALSE, FALSE, FALSE));
5843
5844                 }
5845               else
5846                 {
5847                   // faster than result <- left, anl result,right
5848                   // and better if result is SFR
5849                   if (AOP_TYPE (left) == AOP_ACC)
5850                     {
5851                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5852                                                        FALSE, FALSE, FALSE));
5853                     }
5854                   else
5855                     {
5856                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5857                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5858                       {
5859                           emitcode("mov", "b,a");
5860                           rOp = "b";
5861                       }
5862                         
5863                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5864                       emitcode ("anl", "a,%s", rOp);
5865                     }                   
5866                 }
5867               aopPut (AOP (result), "a", offset);
5868             }
5869         }
5870     }
5871
5872 release:
5873   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5874   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5875   freeAsmop (result, NULL, ic, TRUE);
5876 }
5877
5878
5879 /*-----------------------------------------------------------------*/
5880 /* genOr  - code for or                                            */
5881 /*-----------------------------------------------------------------*/
5882 static void
5883 genOr (iCode * ic, iCode * ifx)
5884 {
5885   operand *left, *right, *result;
5886   int size, offset = 0;
5887   unsigned long lit = 0L;
5888   bool     pushResult;
5889
5890   D (emitcode (";", "genOr "););
5891
5892   AOP_OP_3_NOFATAL (ic, pushResult);
5893   AOP_SET_LOCALS (ic);
5894
5895   if (pushResult)
5896   {
5897       genFarFarLogicOp(ic, "orl");
5898       return;
5899   }
5900
5901
5902 #ifdef DEBUG_TYPE
5903   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5904             AOP_TYPE (result),
5905             AOP_TYPE (left), AOP_TYPE (right));
5906   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5907             AOP_SIZE (result),
5908             AOP_SIZE (left), AOP_SIZE (right));
5909 #endif
5910
5911   /* if left is a literal & right is not then exchange them */
5912   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5913 #ifdef LOGIC_OPS_BROKEN
5914    || AOP_NEEDSACC (left) // I think this is a net loss now.
5915 #endif      
5916       )
5917     {
5918       operand *tmp = right;
5919       right = left;
5920       left = tmp;
5921     }
5922
5923   /* if result = right then exchange them */
5924   if (sameRegs (AOP (result), AOP (right)))
5925     {
5926       operand *tmp = right;
5927       right = left;
5928       left = tmp;
5929     }
5930
5931   /* if right is bit then exchange them */
5932   if (AOP_TYPE (right) == AOP_CRY &&
5933       AOP_TYPE (left) != AOP_CRY)
5934     {
5935       operand *tmp = right;
5936       right = left;
5937       left = tmp;
5938     }
5939   if (AOP_TYPE (right) == AOP_LIT)
5940     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5941
5942   size = AOP_SIZE (result);
5943
5944   // if(bit | yy)
5945   // xx = bit | yy;
5946   if (AOP_TYPE (left) == AOP_CRY)
5947     {
5948       if (AOP_TYPE (right) == AOP_LIT)
5949         {
5950           // c = bit & literal;
5951           if (lit)
5952             {
5953               // lit != 0 => result = 1
5954               if (AOP_TYPE (result) == AOP_CRY)
5955                 {
5956                   if (size)
5957                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5958                   else if (ifx)
5959                     continueIfTrue (ifx);
5960                   goto release;
5961                 }
5962               emitcode ("setb", "c");
5963             }
5964           else
5965             {
5966               // lit == 0 => result = left
5967               if (size && sameRegs (AOP (result), AOP (left)))
5968                 goto release;
5969               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5970             }
5971         }
5972       else
5973         {
5974           if (AOP_TYPE (right) == AOP_CRY)
5975             {
5976               // c = bit | bit;
5977               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5978               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5979             }
5980           else
5981             {
5982               // c = bit | val;
5983               symbol *tlbl = newiTempLabel (NULL);
5984               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5985                 emitcode ("setb", "c");
5986               emitcode ("jb", "%s,%05d$",
5987                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
5988               toBoolean (right);
5989               emitcode ("jnz", "%05d$", tlbl->key + 100);
5990               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5991                 {
5992                   jmpTrueOrFalse (ifx, tlbl);
5993                   goto release;
5994                 }
5995               else
5996                 {
5997                   CLRC;
5998                   emitcode ("", "%05d$:", tlbl->key + 100);
5999                 }
6000             }
6001         }
6002       // bit = c
6003       // val = c
6004       if (size)
6005         outBitC (result);
6006       // if(bit | ...)
6007       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6008         genIfxJump (ifx, "c");
6009       goto release;
6010     }
6011
6012   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6013   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6014   if ((AOP_TYPE (right) == AOP_LIT) &&
6015       (AOP_TYPE (result) == AOP_CRY) &&
6016       (AOP_TYPE (left) != AOP_CRY))
6017     {
6018       if (lit)
6019         {
6020           // result = 1
6021           if (size)
6022             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6023           else
6024             continueIfTrue (ifx);
6025           goto release;
6026         }
6027       else
6028         {
6029           // lit = 0, result = boolean(left)
6030           if (size)
6031             emitcode ("setb", "c");
6032           toBoolean (right);
6033           if (size)
6034             {
6035               symbol *tlbl = newiTempLabel (NULL);
6036               emitcode ("jnz", "%05d$", tlbl->key + 100);
6037               CLRC;
6038               emitcode ("", "%05d$:", tlbl->key + 100);
6039             }
6040           else
6041             {
6042               genIfxJump (ifx, "a");
6043               goto release;
6044             }
6045         }
6046       outBitC (result);
6047       goto release;
6048     }
6049
6050   /* if left is same as result */
6051   if (sameRegs (AOP (result), AOP (left)))
6052     {
6053       for (; size--; offset++)
6054         {
6055           if (AOP_TYPE (right) == AOP_LIT)
6056             {
6057               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6058                 {
6059                   continue;
6060                 }
6061               else
6062                 {
6063                   if (IS_AOP_PREG (left))
6064                     {
6065                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6066                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6067                       aopPut (AOP (result), "a", offset);
6068                     }
6069                   else
6070                     {
6071                       emitcode ("orl", "%s,%s",
6072                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6073                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6074                     }
6075                 }
6076             }
6077           else
6078             {
6079               if (AOP_TYPE (left) == AOP_ACC)
6080                 {
6081                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6082                 }
6083               else
6084                 {
6085                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6086                   if (IS_AOP_PREG (left))
6087                     {
6088                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6089                       aopPut (AOP (result), "a", offset);
6090                     }
6091                   else
6092                     {
6093                       emitcode ("orl", "%s,a",
6094                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6095                     }
6096                 }
6097             }
6098         }
6099     }
6100   else
6101     {
6102       // left & result in different registers
6103       if (AOP_TYPE (result) == AOP_CRY)
6104         {
6105           // result = bit
6106           // if(size), result in bit
6107           // if(!size && ifx), conditional oper: if(left | right)
6108           symbol *tlbl = newiTempLabel (NULL);
6109           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6110           if (size)
6111             emitcode ("setb", "c");
6112           while (sizer--)
6113             {
6114               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6115                 emitcode ("orl", "a,%s",
6116                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6117               } else {
6118                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6119                 emitcode ("orl", "a,%s",
6120                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6121               }
6122               emitcode ("jnz", "%05d$", tlbl->key + 100);
6123               offset++;
6124             }
6125           if (size)
6126             {
6127               CLRC;
6128               emitcode ("", "%05d$:", tlbl->key + 100);
6129               outBitC (result);
6130             }
6131           else if (ifx)
6132             jmpTrueOrFalse (ifx, tlbl);
6133         }
6134       else
6135         {
6136             _startLazyDPSEvaluation();
6137           for (; (size--); offset++)
6138             {
6139               // normal case
6140               // result = left & right
6141               if (AOP_TYPE (right) == AOP_LIT)
6142                 {
6143                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6144                     {
6145                       aopPut (AOP (result),
6146                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6147                               offset);
6148                       continue;
6149                     }
6150                   D (emitcode (";", "better literal OR."););
6151                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6152                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6153                                                     FALSE, FALSE, FALSE));
6154
6155                 }
6156               else
6157                 {
6158                   // faster than result <- left, anl result,right
6159                   // and better if result is SFR
6160                   if (AOP_TYPE (left) == AOP_ACC)
6161                     {
6162                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6163                                                        FALSE, FALSE, FALSE));
6164                     }
6165                   else
6166                     {
6167                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6168                         
6169                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6170                       {
6171                           emitcode("mov", "b,a");
6172                           rOp = "b";
6173                       }
6174                         
6175                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6176                       emitcode ("orl", "a,%s", rOp);
6177                     }
6178                 }
6179               aopPut (AOP (result), "a", offset);
6180             }
6181             _endLazyDPSEvaluation();
6182         }
6183     }
6184
6185 release:
6186   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6187   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6188   freeAsmop (result, NULL, ic, TRUE);
6189 }
6190
6191 /*-----------------------------------------------------------------*/
6192 /* genXor - code for xclusive or                                   */
6193 /*-----------------------------------------------------------------*/
6194 static void
6195 genXor (iCode * ic, iCode * ifx)
6196 {
6197   operand *left, *right, *result;
6198   int size, offset = 0;
6199   unsigned long lit = 0L;
6200   bool pushResult;
6201
6202   D (emitcode (";", "genXor "););
6203
6204   AOP_OP_3_NOFATAL (ic, pushResult);
6205   AOP_SET_LOCALS (ic);
6206
6207   if (pushResult)
6208   {
6209       genFarFarLogicOp(ic, "xrl");
6210       return;
6211   }  
6212
6213 #ifdef DEBUG_TYPE
6214   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6215             AOP_TYPE (result),
6216             AOP_TYPE (left), AOP_TYPE (right));
6217   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6218             AOP_SIZE (result),
6219             AOP_SIZE (left), AOP_SIZE (right));
6220 #endif
6221
6222   /* if left is a literal & right is not ||
6223      if left needs acc & right does not */
6224   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6225 #ifdef LOGIC_OPS_BROKEN      
6226       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6227 #endif
6228      )
6229     {
6230       operand *tmp = right;
6231       right = left;
6232       left = tmp;
6233     }
6234
6235   /* if result = right then exchange them */
6236   if (sameRegs (AOP (result), AOP (right)))
6237     {
6238       operand *tmp = right;
6239       right = left;
6240       left = tmp;
6241     }
6242
6243   /* if right is bit then exchange them */
6244   if (AOP_TYPE (right) == AOP_CRY &&
6245       AOP_TYPE (left) != AOP_CRY)
6246     {
6247       operand *tmp = right;
6248       right = left;
6249       left = tmp;
6250     }
6251   if (AOP_TYPE (right) == AOP_LIT)
6252     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6253
6254   size = AOP_SIZE (result);
6255
6256   // if(bit ^ yy)
6257   // xx = bit ^ yy;
6258   if (AOP_TYPE (left) == AOP_CRY)
6259     {
6260       if (AOP_TYPE (right) == AOP_LIT)
6261         {
6262           // c = bit & literal;
6263           if (lit >> 1)
6264             {
6265               // lit>>1  != 0 => result = 1
6266               if (AOP_TYPE (result) == AOP_CRY)
6267                 {
6268                   if (size)
6269                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6270                   else if (ifx)
6271                     continueIfTrue (ifx);
6272                   goto release;
6273                 }
6274               emitcode ("setb", "c");
6275             }
6276           else
6277             {
6278               // lit == (0 or 1)
6279               if (lit == 0)
6280                 {
6281                   // lit == 0, result = left
6282                   if (size && sameRegs (AOP (result), AOP (left)))
6283                     goto release;
6284                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6285                 }
6286               else
6287                 {
6288                   // lit == 1, result = not(left)
6289                   if (size && sameRegs (AOP (result), AOP (left)))
6290                     {
6291                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6292                       goto release;
6293                     }
6294                   else
6295                     {
6296                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6297                       emitcode ("cpl", "c");
6298                     }
6299                 }
6300             }
6301
6302         }
6303       else
6304         {
6305           // right != literal
6306           symbol *tlbl = newiTempLabel (NULL);
6307           if (AOP_TYPE (right) == AOP_CRY)
6308             {
6309               // c = bit ^ bit;
6310               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6311             }
6312           else
6313             {
6314               int sizer = AOP_SIZE (right);
6315               // c = bit ^ val
6316               // if val>>1 != 0, result = 1
6317               emitcode ("setb", "c");
6318               while (sizer)
6319                 {
6320                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6321                   if (sizer == 1)
6322                     // test the msb of the lsb
6323                     emitcode ("anl", "a,#0xfe");
6324                   emitcode ("jnz", "%05d$", tlbl->key + 100);
6325                   sizer--;
6326                 }
6327               // val = (0,1)
6328               emitcode ("rrc", "a");
6329             }
6330           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6331           emitcode ("cpl", "c");
6332           emitcode ("", "%05d$:", (tlbl->key + 100));
6333         }
6334       // bit = c
6335       // val = c
6336       if (size)
6337         outBitC (result);
6338       // if(bit | ...)
6339       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6340         genIfxJump (ifx, "c");
6341       goto release;
6342     }
6343
6344   if (sameRegs (AOP (result), AOP (left)))
6345     {
6346       /* if left is same as result */
6347       for (; size--; offset++)
6348         {
6349           if (AOP_TYPE (right) == AOP_LIT)
6350             {
6351               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6352                 continue;
6353               else if (IS_AOP_PREG (left))
6354                 {
6355                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6356                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6357                   aopPut (AOP (result), "a", offset);
6358                 }
6359               else
6360                 emitcode ("xrl", "%s,%s",
6361                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6362                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6363             }
6364           else
6365             {
6366               if (AOP_TYPE (left) == AOP_ACC)
6367                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6368               else
6369                 {
6370                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6371                   if (IS_AOP_PREG (left))
6372                     {
6373                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6374                       aopPut (AOP (result), "a", offset);
6375                     }
6376                   else
6377                     emitcode ("xrl", "%s,a",
6378                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6379                 }
6380             }
6381         }
6382     }
6383   else
6384     {
6385       // left & result in different registers
6386       if (AOP_TYPE (result) == AOP_CRY)
6387         {
6388           // result = bit
6389           // if(size), result in bit
6390           // if(!size && ifx), conditional oper: if(left ^ right)
6391           symbol *tlbl = newiTempLabel (NULL);
6392           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6393           if (size)
6394             emitcode ("setb", "c");
6395           while (sizer--)
6396             {
6397               if ((AOP_TYPE (right) == AOP_LIT) &&
6398                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6399                 {
6400                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6401                 }
6402               else
6403                 {
6404                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6405                     emitcode ("xrl", "a,%s",
6406                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6407                   } else {
6408                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6409                     emitcode ("xrl", "a,%s",
6410                               aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6411                   }
6412                 }
6413               emitcode ("jnz", "%05d$", tlbl->key + 100);
6414               offset++;
6415             }
6416           if (size)
6417             {
6418               CLRC;
6419               emitcode ("", "%05d$:", tlbl->key + 100);
6420               outBitC (result);
6421             }
6422           else if (ifx)
6423             jmpTrueOrFalse (ifx, tlbl);
6424         }
6425       else
6426         for (; (size--); offset++)
6427           {
6428             // normal case
6429             // result = left & right
6430             if (AOP_TYPE (right) == AOP_LIT)
6431               {
6432                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6433                   {
6434                     aopPut (AOP (result),
6435                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6436                             offset);
6437                     continue;
6438                   }
6439                 D (emitcode (";", "better literal XOR.");
6440                   );
6441                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6442                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6443                                                   FALSE, FALSE, FALSE));
6444               }
6445             else
6446               {
6447                 // faster than result <- left, anl result,right
6448                 // and better if result is SFR
6449                 if (AOP_TYPE (left) == AOP_ACC)
6450                   {
6451                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6452                                                      FALSE, FALSE, FALSE));
6453                   }
6454                 else
6455                   {
6456                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6457                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6458                       {
6459                           emitcode("mov", "b,a");
6460                           rOp = "b";
6461                       }
6462                         
6463                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6464                       emitcode ("xrl", "a,%s", rOp);
6465                   }
6466               }
6467             aopPut (AOP (result), "a", offset);
6468           }
6469     }
6470
6471 release:
6472   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6473   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6474   freeAsmop (result, NULL, ic, TRUE);
6475 }
6476
6477 /*-----------------------------------------------------------------*/
6478 /* genInline - write the inline code out                           */
6479 /*-----------------------------------------------------------------*/
6480 static void
6481 genInline (iCode * ic)
6482 {
6483   char *buffer, *bp, *bp1;
6484
6485   D (emitcode (";", "genInline ");
6486     );
6487
6488   _G.inLine += (!options.asmpeep);
6489
6490   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6491   strcpy (buffer, IC_INLINE (ic));
6492
6493   /* emit each line as a code */
6494   while (*bp)
6495     {
6496       if (*bp == '\n')
6497         {
6498           *bp++ = '\0';
6499           emitcode (bp1, "");
6500           bp1 = bp;
6501         }
6502       else
6503         {
6504           if (*bp == ':')
6505             {
6506               bp++;
6507               *bp = '\0';
6508               bp++;
6509               emitcode (bp1, "");
6510               bp1 = bp;
6511             }
6512           else
6513             bp++;
6514         }
6515     }
6516   if (bp1 != bp)
6517     emitcode (bp1, "");
6518   /*     emitcode("",buffer); */
6519   _G.inLine -= (!options.asmpeep);
6520 }
6521
6522 /*-----------------------------------------------------------------*/
6523 /* genRRC - rotate right with carry                                */
6524 /*-----------------------------------------------------------------*/
6525 static void
6526 genRRC (iCode * ic)
6527 {
6528   operand *left, *result;
6529   int size, offset = 0;
6530   char *l;
6531
6532   D (emitcode (";", "genRRC ");
6533     );
6534
6535   /* rotate right with carry */
6536   left = IC_LEFT (ic);
6537   result = IC_RESULT (ic);
6538   aopOp (left, ic, FALSE, FALSE);
6539   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6540
6541   /* move it to the result */
6542   size = AOP_SIZE (result);
6543   offset = size - 1;
6544   CLRC;
6545
6546   _startLazyDPSEvaluation ();
6547   while (size--)
6548     {
6549       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6550       MOVA (l);
6551       emitcode ("rrc", "a");
6552       if (AOP_SIZE (result) > 1)
6553         aopPut (AOP (result), "a", offset--);
6554     }
6555   _endLazyDPSEvaluation ();
6556
6557   /* now we need to put the carry into the
6558      highest order byte of the result */
6559   if (AOP_SIZE (result) > 1)
6560     {
6561       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6562       MOVA (l);
6563     }
6564   emitcode ("mov", "acc.7,c");
6565   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6566   freeAsmop (left, NULL, ic, TRUE);
6567   freeAsmop (result, NULL, ic, TRUE);
6568 }
6569
6570 /*-----------------------------------------------------------------*/
6571 /* genRLC - generate code for rotate left with carry               */
6572 /*-----------------------------------------------------------------*/
6573 static void
6574 genRLC (iCode * ic)
6575 {
6576   operand *left, *result;
6577   int size, offset = 0;
6578   char *l;
6579
6580   D (emitcode (";", "genRLC ");
6581     );
6582
6583   /* rotate right with carry */
6584   left = IC_LEFT (ic);
6585   result = IC_RESULT (ic);
6586   aopOp (left, ic, FALSE, FALSE);
6587   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6588
6589   /* move it to the result */
6590   size = AOP_SIZE (result);
6591   offset = 0;
6592   if (size--)
6593     {
6594       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6595       MOVA (l);
6596       emitcode ("add", "a,acc");
6597       if (AOP_SIZE (result) > 1)
6598         {
6599           aopPut (AOP (result), "a", offset++);
6600         }
6601
6602       _startLazyDPSEvaluation ();
6603       while (size--)
6604         {
6605           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6606           MOVA (l);
6607           emitcode ("rlc", "a");
6608           if (AOP_SIZE (result) > 1)
6609             aopPut (AOP (result), "a", offset++);
6610         }
6611       _endLazyDPSEvaluation ();
6612     }
6613   /* now we need to put the carry into the
6614      highest order byte of the result */
6615   if (AOP_SIZE (result) > 1)
6616     {
6617       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6618       MOVA (l);
6619     }
6620   emitcode ("mov", "acc.0,c");
6621   aopPut (AOP (result), "a", 0);
6622   freeAsmop (left, NULL, ic, TRUE);
6623   freeAsmop (result, NULL, ic, TRUE);
6624 }
6625
6626 /*-----------------------------------------------------------------*/
6627 /* genGetHbit - generates code get highest order bit               */
6628 /*-----------------------------------------------------------------*/
6629 static void
6630 genGetHbit (iCode * ic)
6631 {
6632   operand *left, *result;
6633   left = IC_LEFT (ic);
6634   result = IC_RESULT (ic);
6635   aopOp (left, ic, FALSE, FALSE);
6636   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6637
6638   D (emitcode (";", "genGetHbit ");
6639     );
6640
6641   /* get the highest order byte into a */
6642   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6643   if (AOP_TYPE (result) == AOP_CRY)
6644     {
6645       emitcode ("rlc", "a");
6646       outBitC (result);
6647     }
6648   else
6649     {
6650       emitcode ("rl", "a");
6651       emitcode ("anl", "a,#0x01");
6652       outAcc (result);
6653     }
6654
6655
6656   freeAsmop (left, NULL, ic, TRUE);
6657   freeAsmop (result, NULL, ic, TRUE);
6658 }
6659
6660 /*-----------------------------------------------------------------*/
6661 /* AccRol - rotate left accumulator by known count                 */
6662 /*-----------------------------------------------------------------*/
6663 static void
6664 AccRol (int shCount)
6665 {
6666   shCount &= 0x0007;            // shCount : 0..7
6667
6668   switch (shCount)
6669     {
6670     case 0:
6671       break;
6672     case 1:
6673       emitcode ("rl", "a");
6674       break;
6675     case 2:
6676       emitcode ("rl", "a");
6677       emitcode ("rl", "a");
6678       break;
6679     case 3:
6680       emitcode ("swap", "a");
6681       emitcode ("rr", "a");
6682       break;
6683     case 4:
6684       emitcode ("swap", "a");
6685       break;
6686     case 5:
6687       emitcode ("swap", "a");
6688       emitcode ("rl", "a");
6689       break;
6690     case 6:
6691       emitcode ("rr", "a");
6692       emitcode ("rr", "a");
6693       break;
6694     case 7:
6695       emitcode ("rr", "a");
6696       break;
6697     }
6698 }
6699
6700 /*-----------------------------------------------------------------*/
6701 /* AccLsh - left shift accumulator by known count                  */
6702 /*-----------------------------------------------------------------*/
6703 static void
6704 AccLsh (int shCount)
6705 {
6706   if (shCount != 0)
6707     {
6708       if (shCount == 1)
6709         emitcode ("add", "a,acc");
6710       else if (shCount == 2)
6711         {
6712           emitcode ("add", "a,acc");
6713           emitcode ("add", "a,acc");
6714         }
6715       else
6716         {
6717           /* rotate left accumulator */
6718           AccRol (shCount);
6719           /* and kill the lower order bits */
6720           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6721         }
6722     }
6723 }
6724
6725 /*-----------------------------------------------------------------*/
6726 /* AccRsh - right shift accumulator by known count                 */
6727 /*-----------------------------------------------------------------*/
6728 static void
6729 AccRsh (int shCount)
6730 {
6731   if (shCount != 0)
6732     {
6733       if (shCount == 1)
6734         {
6735           CLRC;
6736           emitcode ("rrc", "a");
6737         }
6738       else
6739         {
6740           /* rotate right accumulator */
6741           AccRol (8 - shCount);
6742           /* and kill the higher order bits */
6743           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6744         }
6745     }
6746 }
6747
6748 #ifdef BETTER_LITERAL_SHIFT
6749 /*-----------------------------------------------------------------*/
6750 /* AccSRsh - signed right shift accumulator by known count                 */
6751 /*-----------------------------------------------------------------*/
6752 static void
6753 AccSRsh (int shCount)
6754 {
6755   symbol *tlbl;
6756   if (shCount != 0)
6757     {
6758       if (shCount == 1)
6759         {
6760           emitcode ("mov", "c,acc.7");
6761           emitcode ("rrc", "a");
6762         }
6763       else if (shCount == 2)
6764         {
6765           emitcode ("mov", "c,acc.7");
6766           emitcode ("rrc", "a");
6767           emitcode ("mov", "c,acc.7");
6768           emitcode ("rrc", "a");
6769         }
6770       else
6771         {
6772           tlbl = newiTempLabel (NULL);
6773           /* rotate right accumulator */
6774           AccRol (8 - shCount);
6775           /* and kill the higher order bits */
6776           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6777           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6778           emitcode ("orl", "a,#0x%02x",
6779                     (unsigned char) ~SRMask[shCount]);
6780           emitcode ("", "%05d$:", tlbl->key + 100);
6781         }
6782     }
6783 }
6784 #endif
6785
6786 #ifdef BETTER_LITERAL_SHIFT
6787 /*-----------------------------------------------------------------*/
6788 /* shiftR1Left2Result - shift right one byte from left to result   */
6789 /*-----------------------------------------------------------------*/
6790 static void
6791 shiftR1Left2Result (operand * left, int offl,
6792                     operand * result, int offr,
6793                     int shCount, int sign)
6794 {
6795   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6796   /* shift right accumulator */
6797   if (sign)
6798     AccSRsh (shCount);
6799   else
6800     AccRsh (shCount);
6801   aopPut (AOP (result), "a", offr);
6802 }
6803 #endif
6804
6805 #ifdef BETTER_LITERAL_SHIFT
6806 /*-----------------------------------------------------------------*/
6807 /* shiftL1Left2Result - shift left one byte from left to result    */
6808 /*-----------------------------------------------------------------*/
6809 static void
6810 shiftL1Left2Result (operand * left, int offl,
6811                     operand * result, int offr, int shCount)
6812 {
6813   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6814   /* shift left accumulator */
6815   AccLsh (shCount);
6816   aopPut (AOP (result), "a", offr);
6817 }
6818 #endif
6819
6820 #ifdef BETTER_LITERAL_SHIFT
6821 /*-----------------------------------------------------------------*/
6822 /* movLeft2Result - move byte from left to result                  */
6823 /*-----------------------------------------------------------------*/
6824 static void
6825 movLeft2Result (operand * left, int offl,
6826                 operand * result, int offr, int sign)
6827 {
6828   char *l;
6829   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6830   {
6831       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6832
6833       if (*l == '@' && (IS_AOP_PREG (result)))
6834       {
6835           emitcode ("mov", "a,%s", l);
6836           aopPut (AOP (result), "a", offr);
6837       }
6838       else
6839       {
6840           if (!sign)
6841           {
6842             aopPut (AOP (result), l, offr);
6843           }
6844           else
6845             {
6846               /* MSB sign in acc.7 ! */
6847               if (getDataSize (left) == offl + 1)
6848                 {
6849                   emitcode ("mov", "a,%s", l);
6850                   aopPut (AOP (result), "a", offr);
6851                 }
6852             }
6853       }
6854   }
6855 }
6856 #endif
6857
6858 #ifdef BETTER_LITERAL_SHIFT
6859 /*-----------------------------------------------------------------*/
6860 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6861 /*-----------------------------------------------------------------*/
6862 static void
6863 AccAXRrl1 (char *x)
6864 {
6865   emitcode ("rrc", "a");
6866   emitcode ("xch", "a,%s", x);
6867   emitcode ("rrc", "a");
6868   emitcode ("xch", "a,%s", x);
6869 }
6870 #endif
6871
6872 #ifdef BETTER_LITERAL_SHIFT
6873 //REMOVE ME!!!
6874 /*-----------------------------------------------------------------*/
6875 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6876 /*-----------------------------------------------------------------*/
6877 static void
6878 AccAXLrl1 (char *x)
6879 {
6880   emitcode ("xch", "a,%s", x);
6881   emitcode ("rlc", "a");
6882   emitcode ("xch", "a,%s", x);
6883   emitcode ("rlc", "a");
6884 }
6885 #endif
6886
6887 #ifdef BETTER_LITERAL_SHIFT
6888 /*-----------------------------------------------------------------*/
6889 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6890 /*-----------------------------------------------------------------*/
6891 static void
6892 AccAXLsh1 (char *x)
6893 {
6894   emitcode ("xch", "a,%s", x);
6895   emitcode ("add", "a,acc");
6896   emitcode ("xch", "a,%s", x);
6897   emitcode ("rlc", "a");
6898 }
6899 #endif
6900
6901 #ifdef BETTER_LITERAL_SHIFT
6902 /*-----------------------------------------------------------------*/
6903 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6904 /*-----------------------------------------------------------------*/
6905 static void
6906 AccAXLsh (char *x, int shCount)
6907 {
6908   switch (shCount)
6909     {
6910     case 0:
6911       break;
6912     case 1:
6913       AccAXLsh1 (x);
6914       break;
6915     case 2:
6916       AccAXLsh1 (x);
6917       AccAXLsh1 (x);
6918       break;
6919     case 3:
6920     case 4:
6921     case 5:                     // AAAAABBB:CCCCCDDD
6922
6923       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
6924
6925       emitcode ("anl", "a,#0x%02x",
6926                 SLMask[shCount]);       // BBB00000:CCCCCDDD
6927
6928       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
6929
6930       AccRol (shCount);         // DDDCCCCC:BBB00000
6931
6932       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
6933
6934       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
6935
6936       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
6937
6938       emitcode ("anl", "a,#0x%02x",
6939                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
6940
6941       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
6942
6943       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
6944
6945       break;
6946     case 6:                     // AAAAAABB:CCCCCCDD
6947       emitcode ("anl", "a,#0x%02x",
6948                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6949       emitcode ("mov", "c,acc.0");      // c = B
6950       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6951 #if 0
6952       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6953       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6954 #else
6955       emitcode("rrc","a"); 
6956       emitcode("xch","a,%s", x); 
6957       emitcode("rrc","a"); 
6958       emitcode("mov","c,acc.0"); //<< get correct bit 
6959       emitcode("xch","a,%s", x); 
6960
6961       emitcode("rrc","a"); 
6962       emitcode("xch","a,%s", x); 
6963       emitcode("rrc","a"); 
6964       emitcode("xch","a,%s", x); 
6965 #endif
6966       break;
6967     case 7:                     // a:x <<= 7
6968
6969       emitcode ("anl", "a,#0x%02x",
6970                 SRMask[shCount]);       // 0000000B:CCCCCCCD
6971
6972       emitcode ("mov", "c,acc.0");      // c = B
6973
6974       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
6975
6976       AccAXRrl1 (x);            // BCCCCCCC:D0000000
6977
6978       break;
6979     default:
6980       break;
6981     }
6982 }
6983 #endif
6984
6985 #ifdef BETTER_LITERAL_SHIFT
6986 //REMOVE ME!!!
6987 /*-----------------------------------------------------------------*/
6988 /* AccAXRsh - right shift a:x known count (0..7)                   */
6989 /*-----------------------------------------------------------------*/
6990 static void
6991 AccAXRsh (char *x, int shCount)
6992 {
6993   switch (shCount)
6994     {
6995     case 0:
6996       break;
6997     case 1:
6998       CLRC;
6999       AccAXRrl1 (x);            // 0->a:x
7000
7001       break;
7002     case 2:
7003       CLRC;
7004       AccAXRrl1 (x);            // 0->a:x
7005
7006       CLRC;
7007       AccAXRrl1 (x);            // 0->a:x
7008
7009       break;
7010     case 3:
7011     case 4:
7012     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7013
7014       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
7015
7016       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7017
7018       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7019
7020       emitcode ("anl", "a,#0x%02x",
7021                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7022
7023       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7024
7025       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7026
7027       emitcode ("anl", "a,#0x%02x",
7028                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7029
7030       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7031
7032       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7033
7034       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
7035
7036       break;
7037     case 6:                     // AABBBBBB:CCDDDDDD
7038
7039       emitcode ("mov", "c,acc.7");
7040       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7041
7042       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7043
7044       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7045
7046       emitcode ("anl", "a,#0x%02x",
7047                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7048
7049       break;
7050     case 7:                     // ABBBBBBB:CDDDDDDD
7051
7052       emitcode ("mov", "c,acc.7");      // c = A
7053
7054       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7055
7056       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7057
7058       emitcode ("anl", "a,#0x%02x",
7059                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7060
7061       break;
7062     default:
7063       break;
7064     }
7065 }
7066 #endif
7067
7068 #ifdef BETTER_LITERAL_SHIFT
7069 /*-----------------------------------------------------------------*/
7070 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7071 /*-----------------------------------------------------------------*/
7072 static void
7073 AccAXRshS (char *x, int shCount)
7074 {
7075   symbol *tlbl;
7076   switch (shCount)
7077     {
7078     case 0:
7079       break;
7080     case 1:
7081       emitcode ("mov", "c,acc.7");
7082       AccAXRrl1 (x);            // s->a:x
7083
7084       break;
7085     case 2:
7086       emitcode ("mov", "c,acc.7");
7087       AccAXRrl1 (x);            // s->a:x
7088
7089       emitcode ("mov", "c,acc.7");
7090       AccAXRrl1 (x);            // s->a:x
7091
7092       break;
7093     case 3:
7094     case 4:
7095     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7096
7097       tlbl = newiTempLabel (NULL);
7098       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7099
7100       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7101
7102       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7103
7104       emitcode ("anl", "a,#0x%02x",
7105                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7106
7107       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7108
7109       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7110
7111       emitcode ("anl", "a,#0x%02x",
7112                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7113
7114       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7115
7116       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7117
7118       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7119
7120       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7121       emitcode ("orl", "a,#0x%02x",
7122                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7123
7124       emitcode ("", "%05d$:", tlbl->key + 100);
7125       break;                    // SSSSAAAA:BBBCCCCC
7126
7127     case 6:                     // AABBBBBB:CCDDDDDD
7128
7129       tlbl = newiTempLabel (NULL);
7130       emitcode ("mov", "c,acc.7");
7131       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7132
7133       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7134
7135       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7136
7137       emitcode ("anl", "a,#0x%02x",
7138                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7139
7140       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7141       emitcode ("orl", "a,#0x%02x",
7142                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7143
7144       emitcode ("", "%05d$:", tlbl->key + 100);
7145       break;
7146     case 7:                     // ABBBBBBB:CDDDDDDD
7147
7148       tlbl = newiTempLabel (NULL);
7149       emitcode ("mov", "c,acc.7");      // c = A
7150
7151       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7152
7153       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7154
7155       emitcode ("anl", "a,#0x%02x",
7156                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7157
7158       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7159       emitcode ("orl", "a,#0x%02x",
7160                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7161
7162       emitcode ("", "%05d$:", tlbl->key + 100);
7163       break;
7164     default:
7165       break;
7166     }
7167 }
7168 #endif
7169
7170 #ifdef BETTER_LITERAL_SHIFT
7171 static void
7172 _loadLeftIntoAx(char    **lsb, 
7173                 operand *left, 
7174                 operand *result,
7175                 int     offl,
7176                 int     offr)
7177 {
7178   // Get the initial value from left into a pair of registers.
7179   // MSB must be in A, LSB can be any register.
7180   //
7181   // If the result is held in registers, it is an optimization
7182   // if the LSB can be held in the register which will hold the,
7183   // result LSB since this saves us from having to copy it into
7184   // the result following AccAXLsh.
7185   //
7186   // If the result is addressed indirectly, this is not a gain.
7187   if (AOP_NEEDSACC(result))
7188   {
7189        char *leftByte;
7190        
7191        _startLazyDPSEvaluation();
7192       if (AOP_TYPE(left) == AOP_DPTR2)
7193        {
7194            // Get MSB in A.
7195            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7196            // get LSB in DP2_RESULT_REG.
7197            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7198            assert(!strcmp(leftByte, DP2_RESULT_REG));
7199        }
7200        else
7201        {
7202            // get LSB into DP2_RESULT_REG
7203            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7204            if (strcmp(leftByte, DP2_RESULT_REG))
7205            {
7206                TR_AP("#7");
7207                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7208            }
7209            // And MSB in A.
7210            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7211            assert(strcmp(leftByte, DP2_RESULT_REG));
7212            MOVA(leftByte);
7213        }
7214        _endLazyDPSEvaluation();
7215        *lsb = DP2_RESULT_REG;
7216   }
7217   else
7218   {
7219       if (sameRegs (AOP (result), AOP (left)) &&
7220         ((offl + MSB16) == offr))
7221       {
7222           /* don't crash result[offr] */
7223           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7224           emitcode ("xch", "a,%s", 
7225                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7226       }
7227       else
7228       {
7229           movLeft2Result (left, offl, result, offr, 0);
7230           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7231       }
7232       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7233       assert(strcmp(*lsb,"a"));      
7234   }
7235 }
7236
7237 static void
7238 _storeAxResults(char    *lsb,
7239                 operand *result,
7240                 int     offr)
7241 {
7242   _startLazyDPSEvaluation();
7243   if (AOP_NEEDSACC(result))
7244   {
7245       /* We have to explicitly update the result LSB.
7246        */
7247       emitcode("xch","a,%s", lsb);
7248       aopPut(AOP(result), "a", offr);
7249       emitcode("mov","a,%s", lsb);
7250   }
7251   if (getDataSize (result) > 1)
7252   {
7253       aopPut (AOP (result), "a", offr + MSB16);
7254   }
7255   _endLazyDPSEvaluation();
7256 }
7257
7258 /*-----------------------------------------------------------------*/
7259 /* shiftL2Left2Result - shift left two bytes from left to result   */
7260 /*-----------------------------------------------------------------*/
7261 static void
7262 shiftL2Left2Result (operand * left, int offl,
7263                     operand * result, int offr, int shCount)
7264 {
7265   char *lsb;
7266
7267   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7268   
7269   AccAXLsh (lsb, shCount);
7270   
7271   _storeAxResults(lsb, result, offr);
7272 }
7273 #endif
7274
7275 #ifdef BETTER_LITERAL_SHIFT
7276 /*-----------------------------------------------------------------*/
7277 /* shiftR2Left2Result - shift right two bytes from left to result  */
7278 /*-----------------------------------------------------------------*/
7279 static void
7280 shiftR2Left2Result (operand * left, int offl,
7281                     operand * result, int offr,
7282                     int shCount, int sign)
7283 {
7284   char *lsb;
7285   
7286   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7287   
7288   /* a:x >> shCount (x = lsb(result)) */
7289   if (sign)
7290   {
7291      AccAXRshS(lsb, shCount);
7292   }
7293   else
7294   {
7295     AccAXRsh(lsb, shCount);
7296   }
7297   
7298   _storeAxResults(lsb, result, offr);
7299 }
7300 #endif
7301
7302 #if 0
7303 //REMOVE ME!!!
7304 /*-----------------------------------------------------------------*/
7305 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7306 /*-----------------------------------------------------------------*/
7307 static void
7308 shiftLLeftOrResult (operand * left, int offl,
7309                     operand * result, int offr, int shCount)
7310 {
7311   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7312   /* shift left accumulator */
7313   AccLsh (shCount);
7314   /* or with result */
7315   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7316   /* back to result */
7317   aopPut (AOP (result), "a", offr);
7318 }
7319 #endif
7320
7321 #if 0
7322 //REMOVE ME!!!
7323 /*-----------------------------------------------------------------*/
7324 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7325 /*-----------------------------------------------------------------*/
7326 static void
7327 shiftRLeftOrResult (operand * left, int offl,
7328                     operand * result, int offr, int shCount)
7329 {
7330   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7331   /* shift right accumulator */
7332   AccRsh (shCount);
7333   /* or with result */
7334   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7335   /* back to result */
7336   aopPut (AOP (result), "a", offr);
7337 }
7338 #endif
7339
7340 #ifdef BETTER_LITERAL_SHIFT
7341 /*-----------------------------------------------------------------*/
7342 /* genlshOne - left shift a one byte quantity by known count       */
7343 /*-----------------------------------------------------------------*/
7344 static void
7345 genlshOne (operand * result, operand * left, int shCount)
7346 {
7347   D (emitcode (";", "genlshOne "););
7348   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7349 }
7350 #endif
7351
7352 #ifdef BETTER_LITERAL_SHIFT
7353 /*-----------------------------------------------------------------*/
7354 /* genlshTwo - left shift two bytes by known amount != 0           */
7355 /*-----------------------------------------------------------------*/
7356 static void
7357 genlshTwo (operand * result, operand * left, int shCount)
7358 {
7359   int size;
7360
7361   D (emitcode (";", "genlshTwo "););
7362
7363   size = getDataSize (result);
7364
7365   /* if shCount >= 8 */
7366   if (shCount >= 8)
7367   {
7368       shCount -= 8;
7369
7370       _startLazyDPSEvaluation();
7371
7372       if (size > 1)
7373         {
7374           if (shCount)
7375           {
7376             _endLazyDPSEvaluation();
7377             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7378             aopPut (AOP (result), zero, LSB);       
7379           }
7380           else
7381           {
7382             movLeft2Result (left, LSB, result, MSB16, 0);
7383             aopPut (AOP (result), zero, LSB);
7384             _endLazyDPSEvaluation();
7385           }
7386         }
7387         else
7388         {
7389           aopPut (AOP (result), zero, LSB);
7390           _endLazyDPSEvaluation();
7391         }
7392   }
7393
7394   /*  1 <= shCount <= 7 */
7395   else
7396     {
7397       if (size == 1)
7398       {
7399         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7400       }
7401       else
7402       {
7403         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7404       }
7405     }
7406 }
7407 #endif
7408
7409 #if 0
7410 //REMOVE ME!!!
7411 /*-----------------------------------------------------------------*/
7412 /* shiftLLong - shift left one long from left to result            */
7413 /* offl = LSB or MSB16                                             */
7414 /*-----------------------------------------------------------------*/
7415 static void
7416 shiftLLong (operand * left, operand * result, int offr)
7417 {
7418   char *l;
7419   int size = AOP_SIZE (result);
7420
7421   if (size >= LSB + offr)
7422     {
7423       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7424       MOVA (l);
7425       emitcode ("add", "a,acc");
7426       if (sameRegs (AOP (left), AOP (result)) &&
7427           size >= MSB16 + offr && offr != LSB)
7428         emitcode ("xch", "a,%s",
7429                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7430       else
7431         aopPut (AOP (result), "a", LSB + offr);
7432     }
7433
7434   if (size >= MSB16 + offr)
7435     {
7436       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7437         {
7438           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7439           MOVA (l);
7440         }
7441       emitcode ("rlc", "a");
7442       if (sameRegs (AOP (left), AOP (result)) &&
7443           size >= MSB24 + offr && offr != LSB)
7444         emitcode ("xch", "a,%s",
7445                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7446       else
7447         aopPut (AOP (result), "a", MSB16 + offr);
7448     }
7449
7450   if (size >= MSB24 + offr)
7451     {
7452       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7453         {
7454           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7455           MOVA (l);
7456         }
7457       emitcode ("rlc", "a");
7458       if (sameRegs (AOP (left), AOP (result)) &&
7459           size >= MSB32 + offr && offr != LSB)
7460         emitcode ("xch", "a,%s",
7461                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7462       else
7463         aopPut (AOP (result), "a", MSB24 + offr);
7464     }
7465
7466   if (size > MSB32 + offr)
7467     {
7468       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7469         {
7470           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7471           MOVA (l);
7472         }
7473       emitcode ("rlc", "a");
7474       aopPut (AOP (result), "a", MSB32 + offr);
7475     }
7476   if (offr != LSB)
7477     aopPut (AOP (result), zero, LSB);
7478 }
7479 #endif
7480
7481 #if 0
7482 //REMOVE ME!!!
7483 /*-----------------------------------------------------------------*/
7484 /* genlshFour - shift four byte by a known amount != 0             */
7485 /*-----------------------------------------------------------------*/
7486 static void
7487 genlshFour (operand * result, operand * left, int shCount)
7488 {
7489   int size;
7490
7491   D (emitcode (";", "genlshFour ");
7492     );
7493
7494   size = AOP_SIZE (result);
7495
7496   /* if shifting more that 3 bytes */
7497   if (shCount >= 24)
7498     {
7499       shCount -= 24;
7500       if (shCount)
7501         /* lowest order of left goes to the highest
7502            order of the destination */
7503         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7504       else
7505         movLeft2Result (left, LSB, result, MSB32, 0);
7506       aopPut (AOP (result), zero, LSB);
7507       aopPut (AOP (result), zero, MSB16);
7508       aopPut (AOP (result), zero, MSB24);
7509       return;
7510     }
7511
7512   /* more than two bytes */
7513   else if (shCount >= 16)
7514     {
7515       /* lower order two bytes goes to higher order two bytes */
7516       shCount -= 16;
7517       /* if some more remaining */
7518       if (shCount)
7519         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7520       else
7521         {
7522           movLeft2Result (left, MSB16, result, MSB32, 0);
7523           movLeft2Result (left, LSB, result, MSB24, 0);
7524         }
7525       aopPut (AOP (result), zero, MSB16);
7526       aopPut (AOP (result), zero, LSB);
7527       return;
7528     }
7529
7530   /* if more than 1 byte */
7531   else if (shCount >= 8)
7532     {
7533       /* lower order three bytes goes to higher order  three bytes */
7534       shCount -= 8;
7535       if (size == 2)
7536         {
7537           if (shCount)
7538             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7539           else
7540             movLeft2Result (left, LSB, result, MSB16, 0);
7541         }
7542       else
7543         {                       /* size = 4 */
7544           if (shCount == 0)
7545             {
7546               movLeft2Result (left, MSB24, result, MSB32, 0);
7547               movLeft2Result (left, MSB16, result, MSB24, 0);
7548               movLeft2Result (left, LSB, result, MSB16, 0);
7549               aopPut (AOP (result), zero, LSB);
7550             }
7551           else if (shCount == 1)
7552             shiftLLong (left, result, MSB16);
7553           else
7554             {
7555               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7556               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7557               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7558               aopPut (AOP (result), zero, LSB);
7559             }
7560         }
7561     }
7562
7563   /* 1 <= shCount <= 7 */
7564   else if (shCount <= 2)
7565     {
7566       shiftLLong (left, result, LSB);
7567       if (shCount == 2)
7568         shiftLLong (result, result, LSB);
7569     }
7570   /* 3 <= shCount <= 7, optimize */
7571   else
7572     {
7573       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7574       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7575       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7576     }
7577 }
7578 #endif
7579
7580 #ifdef BETTER_LITERAL_SHIFT
7581 /*-----------------------------------------------------------------*/
7582 /* genLeftShiftLiteral - left shifting by known count              */
7583 /*-----------------------------------------------------------------*/
7584 static bool
7585 genLeftShiftLiteral (operand * left,
7586                      operand * right,
7587                      operand * result,
7588                      iCode * ic)
7589 {
7590   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7591   int size;
7592
7593   size = getSize (operandType (result));
7594
7595   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7596
7597   /* We only handle certain easy cases so far. */
7598   if ((shCount != 0)
7599    && (shCount < (size * 8))
7600    && (size != 1)
7601    && (size != 2))
7602   {
7603       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7604       return FALSE;
7605   }
7606
7607   freeAsmop (right, NULL, ic, TRUE);
7608
7609   aopOp(left, ic, FALSE, FALSE);
7610   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7611
7612 #if 1 // debug spew
7613   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7614   {
7615         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7616         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7617         {
7618            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7619         }
7620   }
7621   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7622   {
7623         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7624         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7625         {
7626            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7627         }       
7628   }  
7629 #endif
7630   
7631 #if VIEW_SIZE
7632   emitcode ("; shift left ", "result %d, left %d", size,
7633             AOP_SIZE (left));
7634 #endif
7635
7636   /* I suppose that the left size >= result size */
7637   if (shCount == 0)
7638   {
7639         _startLazyDPSEvaluation();
7640         while (size--)
7641         {
7642           movLeft2Result (left, size, result, size, 0);
7643         }
7644         _endLazyDPSEvaluation();
7645   }
7646   else if (shCount >= (size * 8))
7647   {
7648     _startLazyDPSEvaluation();
7649     while (size--)
7650     {
7651       aopPut (AOP (result), zero, size);
7652     }
7653     _endLazyDPSEvaluation();
7654   }
7655   else
7656   {
7657       switch (size)
7658         {
7659         case 1:
7660           genlshOne (result, left, shCount);
7661           break;
7662
7663         case 2:
7664           genlshTwo (result, left, shCount);
7665           break;
7666 #if 0
7667         case 4:
7668           genlshFour (result, left, shCount);
7669           break;
7670 #endif
7671         default:
7672           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7673           break;
7674         }
7675     }
7676   freeAsmop (left, NULL, ic, TRUE);
7677   freeAsmop (result, NULL, ic, TRUE);
7678   return TRUE;
7679 }
7680 #endif
7681
7682 /*-----------------------------------------------------------------*/
7683 /* genLeftShift - generates code for left shifting                 */
7684 /*-----------------------------------------------------------------*/
7685 static void
7686 genLeftShift (iCode * ic)
7687 {
7688   operand *left, *right, *result;
7689   int size, offset;
7690   char *l;
7691   symbol *tlbl, *tlbl1;
7692
7693   D (emitcode (";", "genLeftShift "););
7694
7695   right = IC_RIGHT (ic);
7696   left = IC_LEFT (ic);
7697   result = IC_RESULT (ic);
7698
7699   aopOp (right, ic, FALSE, FALSE);
7700
7701
7702 #ifdef BETTER_LITERAL_SHIFT
7703   /* if the shift count is known then do it
7704      as efficiently as possible */
7705   if (AOP_TYPE (right) == AOP_LIT)
7706     {
7707       if (genLeftShiftLiteral (left, right, result, ic))
7708       {
7709         return;
7710       }
7711     }
7712 #endif
7713
7714   /* shift count is unknown then we have to form
7715      a loop get the loop count in B : Note: we take
7716      only the lower order byte since shifting
7717      more that 32 bits make no sense anyway, ( the
7718      largest size of an object can be only 32 bits ) */
7719
7720   if (AOP_TYPE (right) == AOP_LIT)
7721   {
7722       /* Really should be handled by genLeftShiftLiteral,
7723        * but since I'm too lazy to fix that today, at least we can make
7724        * some small improvement.
7725        */
7726        emitcode("mov", "b,#0x%02x",
7727                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7728   }
7729   else
7730   {
7731         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7732         emitcode ("inc", "b");
7733   }
7734   freeAsmop (right, NULL, ic, TRUE);
7735   aopOp (left, ic, FALSE, FALSE);
7736   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7737
7738   /* now move the left to the result if they are not the
7739      same */
7740   if (!sameRegs (AOP (left), AOP (result)) &&
7741       AOP_SIZE (result) > 1)
7742     {
7743
7744       size = AOP_SIZE (result);
7745       offset = 0;
7746       _startLazyDPSEvaluation ();
7747       while (size--)
7748         {
7749           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7750           if (*l == '@' && (IS_AOP_PREG (result)))
7751             {
7752
7753               emitcode ("mov", "a,%s", l);
7754               aopPut (AOP (result), "a", offset);
7755             }
7756           else
7757             aopPut (AOP (result), l, offset);
7758           offset++;
7759         }
7760       _endLazyDPSEvaluation ();
7761     }
7762
7763   tlbl = newiTempLabel (NULL);
7764   size = AOP_SIZE (result);
7765   offset = 0;
7766   tlbl1 = newiTempLabel (NULL);
7767
7768   /* if it is only one byte then */
7769   if (size == 1)
7770     {
7771       symbol *tlbl1 = newiTempLabel (NULL);
7772
7773       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7774       MOVA (l);
7775       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7776       emitcode ("", "%05d$:", tlbl->key + 100);
7777       emitcode ("add", "a,acc");
7778       emitcode ("", "%05d$:", tlbl1->key + 100);
7779       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7780       aopPut (AOP (result), "a", 0);
7781       goto release;
7782     }
7783
7784   reAdjustPreg (AOP (result));
7785
7786   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7787   emitcode ("", "%05d$:", tlbl->key + 100);
7788   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7789   MOVA (l);
7790   emitcode ("add", "a,acc");
7791   aopPut (AOP (result), "a", offset++);
7792   _startLazyDPSEvaluation ();
7793   while (--size)
7794     {
7795       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7796       MOVA (l);
7797       emitcode ("rlc", "a");
7798       aopPut (AOP (result), "a", offset++);
7799     }
7800   _endLazyDPSEvaluation ();
7801   reAdjustPreg (AOP (result));
7802
7803   emitcode ("", "%05d$:", tlbl1->key + 100);
7804   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7805 release:
7806   freeAsmop (left, NULL, ic, TRUE);
7807   freeAsmop (result, NULL, ic, TRUE);
7808 }
7809
7810 #ifdef BETTER_LITERAL_SHIFT
7811 /*-----------------------------------------------------------------*/
7812 /* genrshOne - right shift a one byte quantity by known count      */
7813 /*-----------------------------------------------------------------*/
7814 static void
7815 genrshOne (operand * result, operand * left,
7816            int shCount, int sign)
7817 {
7818   D (emitcode (";", "genrshOne"););
7819   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7820 }
7821 #endif
7822
7823 #ifdef BETTER_LITERAL_SHIFT
7824 /*-----------------------------------------------------------------*/
7825 /* genrshTwo - right shift two bytes by known amount != 0          */
7826 /*-----------------------------------------------------------------*/
7827 static void
7828 genrshTwo (operand * result, operand * left,
7829            int shCount, int sign)
7830 {
7831   D (emitcode (";", "genrshTwo"););
7832
7833   /* if shCount >= 8 */
7834   if (shCount >= 8)
7835     {
7836       shCount -= 8;
7837       _startLazyDPSEvaluation();
7838       if (shCount)
7839       {
7840         shiftR1Left2Result (left, MSB16, result, LSB,
7841                             shCount, sign);
7842       }                     
7843       else
7844       {
7845         movLeft2Result (left, MSB16, result, LSB, sign);
7846       }
7847       addSign (result, MSB16, sign);
7848       _endLazyDPSEvaluation();
7849     }
7850
7851   /*  1 <= shCount <= 7 */
7852   else
7853   {
7854     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7855   }
7856 }
7857 #endif
7858
7859 #if 0
7860 //REMOVE ME!!!
7861 /*-----------------------------------------------------------------*/
7862 /* shiftRLong - shift right one long from left to result           */
7863 /* offl = LSB or MSB16                                             */
7864 /*-----------------------------------------------------------------*/
7865 static void
7866 shiftRLong (operand * left, int offl,
7867             operand * result, int sign)
7868 {
7869   int isSameRegs=sameRegs(AOP(left),AOP(result));
7870
7871   if (isSameRegs && offl>1) {
7872     // we are in big trouble, but this shouldn't happen
7873     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7874   }
7875
7876   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7877   
7878   if (offl==MSB16) {
7879     // shift is > 8
7880     if (sign) {
7881       emitcode ("rlc", "a");
7882       emitcode ("subb", "a,acc");
7883       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7884     } else {
7885       aopPut (AOP(result), zero, MSB32);
7886     }
7887   }
7888
7889   if (!sign) {
7890     emitcode ("clr", "c");
7891   } else {
7892     emitcode ("mov", "c,acc.7");
7893   }
7894
7895   emitcode ("rrc", "a");
7896
7897   if (isSameRegs && offl==MSB16) {
7898     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7899   } else {
7900     aopPut (AOP (result), "a", MSB32);
7901     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7902   }
7903
7904   emitcode ("rrc", "a");
7905   if (isSameRegs && offl==1) {
7906     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7907   } else {
7908     aopPut (AOP (result), "a", MSB24);
7909     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7910   }
7911   emitcode ("rrc", "a");
7912   aopPut (AOP (result), "a", MSB16 - offl);
7913
7914   if (offl == LSB)
7915     {
7916       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7917       emitcode ("rrc", "a");
7918       aopPut (AOP (result), "a", LSB);
7919     }
7920 }
7921 #endif
7922
7923 #if 0
7924 //REMOVE ME!!!
7925 /*-----------------------------------------------------------------*/
7926 /* genrshFour - shift four byte by a known amount != 0             */
7927 /*-----------------------------------------------------------------*/
7928 static void
7929 genrshFour (operand * result, operand * left,
7930             int shCount, int sign)
7931 {
7932   D (emitcode (";", "genrshFour");
7933     );
7934
7935   /* if shifting more that 3 bytes */
7936   if (shCount >= 24)
7937     {
7938       shCount -= 24;
7939       if (shCount)
7940         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7941       else
7942         movLeft2Result (left, MSB32, result, LSB, sign);
7943       addSign (result, MSB16, sign);
7944     }
7945   else if (shCount >= 16)
7946     {
7947       shCount -= 16;
7948       if (shCount)
7949         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7950       else
7951         {
7952           movLeft2Result (left, MSB24, result, LSB, 0);
7953           movLeft2Result (left, MSB32, result, MSB16, sign);
7954         }
7955       addSign (result, MSB24, sign);
7956     }
7957   else if (shCount >= 8)
7958     {
7959       shCount -= 8;
7960       if (shCount == 1)
7961         shiftRLong (left, MSB16, result, sign);
7962       else if (shCount == 0)
7963         {
7964           movLeft2Result (left, MSB16, result, LSB, 0);
7965           movLeft2Result (left, MSB24, result, MSB16, 0);
7966           movLeft2Result (left, MSB32, result, MSB24, sign);
7967           addSign (result, MSB32, sign);
7968         }
7969       else
7970         {
7971           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7972           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7973           /* the last shift is signed */
7974           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7975           addSign (result, MSB32, sign);
7976         }
7977     }
7978   else
7979     {                           /* 1 <= shCount <= 7 */
7980       if (shCount <= 2)
7981         {
7982           shiftRLong (left, LSB, result, sign);
7983           if (shCount == 2)
7984             shiftRLong (result, LSB, result, sign);
7985         }
7986       else
7987         {
7988           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7989           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7990           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7991         }
7992     }
7993 }
7994 #endif
7995
7996 #ifdef BETTER_LITERAL_SHIFT
7997 /*-----------------------------------------------------------------*/
7998 /* genRightShiftLiteral - right shifting by known count            */
7999 /*-----------------------------------------------------------------*/
8000 static bool
8001 genRightShiftLiteral (operand * left,
8002                       operand * right,
8003                       operand * result,
8004                       iCode * ic,
8005                       int sign)
8006 {
8007   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8008   int size;
8009
8010   size = getSize (operandType (result));
8011
8012   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8013
8014   /* We only handle certain easy cases so far. */
8015   if ((shCount != 0)
8016    && (shCount < (size * 8))
8017    && (size != 1)
8018    && (size != 2))
8019   {
8020       D(emitcode (";", "genRightShiftLiteral wimping out"););   
8021       return FALSE;
8022   }
8023
8024   freeAsmop (right, NULL, ic, TRUE);
8025
8026   aopOp (left, ic, FALSE, FALSE);
8027   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8028
8029 #if VIEW_SIZE
8030   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8031             AOP_SIZE (left));
8032 #endif
8033
8034   /* test the LEFT size !!! */
8035
8036   /* I suppose that the left size >= result size */
8037   if (shCount == 0)
8038   {
8039       size = getDataSize (result);
8040       _startLazyDPSEvaluation();
8041       while (size--)
8042       {
8043         movLeft2Result (left, size, result, size, 0);
8044       }
8045       _endLazyDPSEvaluation();
8046   }
8047   else if (shCount >= (size * 8))
8048     {
8049       if (sign)
8050       {
8051         /* get sign in acc.7 */
8052         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8053       }
8054       addSign (result, LSB, sign);
8055     }
8056   else
8057     {
8058       switch (size)
8059         {
8060         case 1:
8061           genrshOne (result, left, shCount, sign);
8062           break;
8063
8064         case 2:
8065           genrshTwo (result, left, shCount, sign);
8066           break;
8067 #if 0
8068         case 4:
8069           genrshFour (result, left, shCount, sign);
8070           break;
8071 #endif    
8072         default:
8073           break;
8074         }
8075
8076       freeAsmop (left, NULL, ic, TRUE);
8077       freeAsmop (result, NULL, ic, TRUE);
8078     }
8079     return TRUE;
8080 }
8081 #endif
8082
8083 /*-----------------------------------------------------------------*/
8084 /* genSignedRightShift - right shift of signed number              */
8085 /*-----------------------------------------------------------------*/
8086 static void
8087 genSignedRightShift (iCode * ic)
8088 {
8089   operand *right, *left, *result;
8090   int size, offset;
8091   char *l;
8092   symbol *tlbl, *tlbl1;
8093
8094   D (emitcode (";", "genSignedRightShift "););
8095
8096   /* we do it the hard way put the shift count in b
8097      and loop thru preserving the sign */
8098
8099   right = IC_RIGHT (ic);
8100   left = IC_LEFT (ic);
8101   result = IC_RESULT (ic);
8102
8103   aopOp (right, ic, FALSE, FALSE);
8104
8105 #ifdef BETTER_LITERAL_SHIFT
8106   if (AOP_TYPE (right) == AOP_LIT)
8107     {
8108       if (genRightShiftLiteral (left, right, result, ic, 1))
8109       {
8110         return;
8111       }
8112     }
8113 #endif
8114   /* shift count is unknown then we have to form
8115      a loop get the loop count in B : Note: we take
8116      only the lower order byte since shifting
8117      more that 32 bits make no sense anyway, ( the
8118      largest size of an object can be only 32 bits ) */
8119
8120   if (AOP_TYPE (right) == AOP_LIT)
8121   {
8122       /* Really should be handled by genRightShiftLiteral,
8123        * but since I'm too lazy to fix that today, at least we can make
8124        * some small improvement.
8125        */
8126        emitcode("mov", "b,#0x%02x",
8127                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8128   }
8129   else
8130   {
8131         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8132         emitcode ("inc", "b");
8133   }
8134   freeAsmop (right, NULL, ic, TRUE);
8135   aopOp (left, ic, FALSE, FALSE);
8136   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8137
8138   /* now move the left to the result if they are not the
8139      same */
8140   if (!sameRegs (AOP (left), AOP (result)) &&
8141       AOP_SIZE (result) > 1)
8142     {
8143
8144       size = AOP_SIZE (result);
8145       offset = 0;
8146       _startLazyDPSEvaluation ();
8147       while (size--)
8148         {
8149           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8150           if (*l == '@' && IS_AOP_PREG (result))
8151             {
8152
8153               emitcode ("mov", "a,%s", l);
8154               aopPut (AOP (result), "a", offset);
8155             }
8156           else
8157             aopPut (AOP (result), l, offset);
8158           offset++;
8159         }
8160       _endLazyDPSEvaluation ();
8161     }
8162
8163   /* mov the highest order bit to OVR */
8164   tlbl = newiTempLabel (NULL);
8165   tlbl1 = newiTempLabel (NULL);
8166
8167   size = AOP_SIZE (result);
8168   offset = size - 1;
8169   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8170   emitcode ("rlc", "a");
8171   emitcode ("mov", "ov,c");
8172   /* if it is only one byte then */
8173   if (size == 1)
8174     {
8175       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8176       MOVA (l);
8177       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8178       emitcode ("", "%05d$:", tlbl->key + 100);
8179       emitcode ("mov", "c,ov");
8180       emitcode ("rrc", "a");
8181       emitcode ("", "%05d$:", tlbl1->key + 100);
8182       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8183       aopPut (AOP (result), "a", 0);
8184       goto release;
8185     }
8186
8187   reAdjustPreg (AOP (result));
8188   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8189   emitcode ("", "%05d$:", tlbl->key + 100);
8190   emitcode ("mov", "c,ov");
8191   _startLazyDPSEvaluation ();
8192   while (size--)
8193     {
8194       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8195       MOVA (l);
8196       emitcode ("rrc", "a");
8197       aopPut (AOP (result), "a", offset--);
8198     }
8199   _endLazyDPSEvaluation ();
8200   reAdjustPreg (AOP (result));
8201   emitcode ("", "%05d$:", tlbl1->key + 100);
8202   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8203
8204 release:
8205   freeAsmop (left, NULL, ic, TRUE);
8206   freeAsmop (result, NULL, ic, TRUE);
8207 }
8208
8209 /*-----------------------------------------------------------------*/
8210 /* genRightShift - generate code for right shifting                */
8211 /*-----------------------------------------------------------------*/
8212 static void
8213 genRightShift (iCode * ic)
8214 {
8215   operand *right, *left, *result;
8216   sym_link *retype;
8217   int size, offset;
8218   char *l;
8219   symbol *tlbl, *tlbl1;
8220
8221   D (emitcode (";", "genRightShift "););
8222
8223   /* if signed then we do it the hard way preserve the
8224      sign bit moving it inwards */
8225   retype = getSpec (operandType (IC_RESULT (ic)));
8226
8227   if (!SPEC_USIGN (retype))
8228     {
8229       genSignedRightShift (ic);
8230       return;
8231     }
8232
8233   /* signed & unsigned types are treated the same : i.e. the
8234      signed is NOT propagated inwards : quoting from the
8235      ANSI - standard : "for E1 >> E2, is equivalent to division
8236      by 2**E2 if unsigned or if it has a non-negative value,
8237      otherwise the result is implementation defined ", MY definition
8238      is that the sign does not get propagated */
8239
8240   right = IC_RIGHT (ic);
8241   left = IC_LEFT (ic);
8242   result = IC_RESULT (ic);
8243
8244   aopOp (right, ic, FALSE, FALSE);
8245
8246 #ifdef BETTER_LITERAL_SHIFT
8247   /* if the shift count is known then do it
8248      as efficiently as possible */
8249   if (AOP_TYPE (right) == AOP_LIT)
8250     {
8251       if (genRightShiftLiteral (left, right, result, ic, 0))
8252       {
8253         return;
8254       }
8255     }
8256 #endif
8257
8258   /* shift count is unknown then we have to form
8259      a loop get the loop count in B : Note: we take
8260      only the lower order byte since shifting
8261      more that 32 bits make no sense anyway, ( the
8262      largest size of an object can be only 32 bits ) */
8263   
8264   if (AOP_TYPE (right) == AOP_LIT)
8265   {
8266       /* Really should be handled by genRightShiftLiteral,
8267        * but since I'm too lazy to fix that today, at least we can make
8268        * some small improvement.
8269        */
8270        emitcode("mov", "b,#0x%02x",
8271                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8272   }
8273   else
8274   {
8275         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8276         emitcode ("inc", "b");
8277   }
8278   freeAsmop (right, NULL, ic, TRUE);
8279   aopOp (left, ic, FALSE, FALSE);
8280   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8281
8282   /* now move the left to the result if they are not the
8283      same */
8284   if (!sameRegs (AOP (left), AOP (result)) &&
8285       AOP_SIZE (result) > 1)
8286     {
8287
8288       size = AOP_SIZE (result);
8289       offset = 0;
8290       _startLazyDPSEvaluation ();
8291       while (size--)
8292         {
8293           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8294           if (*l == '@' && IS_AOP_PREG (result))
8295             {
8296
8297               emitcode ("mov", "a,%s", l);
8298               aopPut (AOP (result), "a", offset);
8299             }
8300           else
8301             aopPut (AOP (result), l, offset);
8302           offset++;
8303         }
8304       _endLazyDPSEvaluation ();
8305     }
8306
8307   tlbl = newiTempLabel (NULL);
8308   tlbl1 = newiTempLabel (NULL);
8309   size = AOP_SIZE (result);
8310   offset = size - 1;
8311
8312   /* if it is only one byte then */
8313   if (size == 1)
8314     {
8315       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8316       MOVA (l);
8317       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8318       emitcode ("", "%05d$:", tlbl->key + 100);
8319       CLRC;
8320       emitcode ("rrc", "a");
8321       emitcode ("", "%05d$:", tlbl1->key + 100);
8322       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8323       aopPut (AOP (result), "a", 0);
8324       goto release;
8325     }
8326
8327   reAdjustPreg (AOP (result));
8328   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8329   emitcode ("", "%05d$:", tlbl->key + 100);
8330   CLRC;
8331   _startLazyDPSEvaluation ();
8332   while (size--)
8333     {
8334       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8335       MOVA (l);
8336       emitcode ("rrc", "a");
8337       aopPut (AOP (result), "a", offset--);
8338     }
8339   _endLazyDPSEvaluation ();
8340   reAdjustPreg (AOP (result));
8341
8342   emitcode ("", "%05d$:", tlbl1->key + 100);
8343   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8344
8345 release:
8346   freeAsmop (left, NULL, ic, TRUE);
8347   freeAsmop (result, NULL, ic, TRUE);
8348 }
8349
8350 /*-----------------------------------------------------------------*/
8351 /* genUnpackBits - generates code for unpacking bits               */
8352 /*-----------------------------------------------------------------*/
8353 static void
8354 genUnpackBits (operand * result, char *rname, int ptype)
8355 {
8356   int shCnt;
8357   int rlen = 0;
8358   sym_link *etype;
8359   int offset = 0;
8360
8361   D (emitcode (";", "genUnpackBits ");
8362     );
8363
8364   etype = getSpec (operandType (result));
8365
8366   /* read the first byte  */
8367   switch (ptype)
8368     {
8369
8370     case POINTER:
8371     case IPOINTER:
8372       emitcode ("mov", "a,@%s", rname);
8373       break;
8374
8375     case PPOINTER:
8376       emitcode ("movx", "a,@%s", rname);
8377       break;
8378
8379     case FPOINTER:
8380       emitcode ("movx", "a,@dptr");
8381       break;
8382
8383     case CPOINTER:
8384       emitcode ("clr", "a");
8385       emitcode ("movc", "a,@a+dptr");
8386       break;
8387
8388     case GPOINTER:
8389       emitcode ("lcall", "__gptrget");
8390       break;
8391     }
8392
8393   /* if we have bitdisplacement then it fits   */
8394   /* into this byte completely or if length is */
8395   /* less than a byte                          */
8396   if ((shCnt = SPEC_BSTR (etype)) ||
8397       (SPEC_BLEN (etype) <= 8))
8398     {
8399
8400       /* shift right acc */
8401       AccRsh (shCnt);
8402
8403       emitcode ("anl", "a,#0x%02x",
8404                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8405       aopPut (AOP (result), "a", offset);
8406       return;
8407     }
8408
8409   /* bit field did not fit in a byte  */
8410   rlen = SPEC_BLEN (etype) - 8;
8411   aopPut (AOP (result), "a", offset++);
8412
8413   while (1)
8414     {
8415
8416       switch (ptype)
8417         {
8418         case POINTER:
8419         case IPOINTER:
8420           emitcode ("inc", "%s", rname);
8421           emitcode ("mov", "a,@%s", rname);
8422           break;
8423
8424         case PPOINTER:
8425           emitcode ("inc", "%s", rname);
8426           emitcode ("movx", "a,@%s", rname);
8427           break;
8428
8429         case FPOINTER:
8430           emitcode ("inc", "dptr");
8431           emitcode ("movx", "a,@dptr");
8432           break;
8433
8434         case CPOINTER:
8435           emitcode ("clr", "a");
8436           emitcode ("inc", "dptr");
8437           emitcode ("movc", "a,@a+dptr");
8438           break;
8439
8440         case GPOINTER:
8441           emitcode ("inc", "dptr");
8442           emitcode ("lcall", "__gptrget");
8443           break;
8444         }
8445
8446       rlen -= 8;
8447       /* if we are done */
8448       if (rlen < 8)
8449         break;
8450
8451       aopPut (AOP (result), "a", offset++);
8452
8453     }
8454
8455   if (rlen)
8456     {
8457       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8458       aopPut (AOP (result), "a", offset);
8459     }
8460
8461   return;
8462 }
8463
8464
8465 /*-----------------------------------------------------------------*/
8466 /* genDataPointerGet - generates code when ptr offset is known     */
8467 /*-----------------------------------------------------------------*/
8468 static void
8469 genDataPointerGet (operand * left,
8470                    operand * result,
8471                    iCode * ic)
8472 {
8473   char *l;
8474   char buffer[256];
8475   int size, offset = 0;
8476   aopOp (result, ic, TRUE, FALSE);
8477
8478   /* get the string representation of the name */
8479   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8480   size = AOP_SIZE (result);
8481   _startLazyDPSEvaluation ();
8482   while (size--)
8483     {
8484       if (offset)
8485         sprintf (buffer, "(%s + %d)", l + 1, offset);
8486       else
8487         sprintf (buffer, "%s", l + 1);
8488       aopPut (AOP (result), buffer, offset++);
8489     }
8490   _endLazyDPSEvaluation ();
8491
8492   freeAsmop (left, NULL, ic, TRUE);
8493   freeAsmop (result, NULL, ic, TRUE);
8494 }
8495
8496 /*-----------------------------------------------------------------*/
8497 /* genNearPointerGet - emitcode for near pointer fetch             */
8498 /*-----------------------------------------------------------------*/
8499 static void
8500 genNearPointerGet (operand * left,
8501                    operand * result,
8502                    iCode * ic)
8503 {
8504   asmop *aop = NULL;
8505   regs *preg = NULL;
8506   char *rname;
8507   sym_link *rtype, *retype, *letype;
8508   sym_link *ltype = operandType (left);
8509   char buffer[80];
8510
8511   rtype = operandType (result);
8512   retype = getSpec (rtype);
8513   letype = getSpec (ltype);
8514
8515   aopOp (left, ic, FALSE, FALSE);
8516
8517   /* if left is rematerialisable and
8518      result is not bit variable type and
8519      the left is pointer to data space i.e
8520      lower 128 bytes of space */
8521   if (AOP_TYPE (left) == AOP_IMMD &&
8522       !IS_BITVAR (retype) &&
8523       !IS_BITVAR (letype) &&
8524       DCL_TYPE (ltype) == POINTER)
8525     {
8526       genDataPointerGet (left, result, ic);
8527       return;
8528     }
8529
8530   /* if the value is already in a pointer register
8531      then don't need anything more */
8532   if (!AOP_INPREG (AOP (left)))
8533     {
8534       /* otherwise get a free pointer register */
8535       aop = newAsmop (0);
8536       preg = getFreePtr (ic, &aop, FALSE);
8537       emitcode ("mov", "%s,%s",
8538                 preg->name,
8539                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8540       rname = preg->name;
8541     }
8542   else
8543     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8544
8545   freeAsmop (left, NULL, ic, TRUE);
8546   aopOp (result, ic, FALSE, FALSE);
8547
8548   /* if bitfield then unpack the bits */
8549   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8550     genUnpackBits (result, rname, POINTER);
8551   else
8552     {
8553       /* we have can just get the values */
8554       int size = AOP_SIZE (result);
8555       int offset = 0;
8556
8557       while (size--)
8558         {
8559           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8560             {
8561
8562               emitcode ("mov", "a,@%s", rname);
8563               aopPut (AOP (result), "a", offset);
8564             }
8565           else
8566             {
8567               sprintf (buffer, "@%s", rname);
8568               aopPut (AOP (result), buffer, offset);
8569             }
8570           offset++;
8571           if (size)
8572             emitcode ("inc", "%s", rname);
8573         }
8574     }
8575
8576   /* now some housekeeping stuff */
8577   if (aop)
8578     {
8579       /* we had to allocate for this iCode */
8580       freeAsmop (NULL, aop, ic, TRUE);
8581     }
8582   else
8583     {
8584       /* we did not allocate which means left
8585          already in a pointer register, then
8586          if size > 0 && this could be used again
8587          we have to point it back to where it
8588          belongs */
8589       if (AOP_SIZE (result) > 1 &&
8590           !OP_SYMBOL (left)->remat &&
8591           (OP_SYMBOL (left)->liveTo > ic->seq ||
8592            ic->depth))
8593         {
8594           int size = AOP_SIZE (result) - 1;
8595           while (size--)
8596             emitcode ("dec", "%s", rname);
8597         }
8598     }
8599
8600   /* done */
8601   freeAsmop (result, NULL, ic, TRUE);
8602
8603 }
8604
8605 /*-----------------------------------------------------------------*/
8606 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8607 /*-----------------------------------------------------------------*/
8608 static void
8609 genPagedPointerGet (operand * left,
8610                     operand * result,
8611                     iCode * ic)
8612 {
8613   asmop *aop = NULL;
8614   regs *preg = NULL;
8615   char *rname;
8616   sym_link *rtype, *retype, *letype;
8617
8618   rtype = operandType (result);
8619   retype = getSpec (rtype);
8620   letype = getSpec (operandType (left));
8621   aopOp (left, ic, FALSE, FALSE);
8622
8623   /* if the value is already in a pointer register
8624      then don't need anything more */
8625   if (!AOP_INPREG (AOP (left)))
8626     {
8627       /* otherwise get a free pointer register */
8628       aop = newAsmop (0);
8629       preg = getFreePtr (ic, &aop, FALSE);
8630       emitcode ("mov", "%s,%s",
8631                 preg->name,
8632                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8633       rname = preg->name;
8634     }
8635   else
8636     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8637
8638   freeAsmop (left, NULL, ic, TRUE);
8639   aopOp (result, ic, FALSE, FALSE);
8640
8641   /* if bitfield then unpack the bits */
8642   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8643     genUnpackBits (result, rname, PPOINTER);
8644   else
8645     {
8646       /* we have can just get the values */
8647       int size = AOP_SIZE (result);
8648       int offset = 0;
8649
8650       while (size--)
8651         {
8652
8653           emitcode ("movx", "a,@%s", rname);
8654           aopPut (AOP (result), "a", offset);
8655
8656           offset++;
8657
8658           if (size)
8659             emitcode ("inc", "%s", rname);
8660         }
8661     }
8662
8663   /* now some housekeeping stuff */
8664   if (aop)
8665     {
8666       /* we had to allocate for this iCode */
8667       freeAsmop (NULL, aop, ic, TRUE);
8668     }
8669   else
8670     {
8671       /* we did not allocate which means left
8672          already in a pointer register, then
8673          if size > 0 && this could be used again
8674          we have to point it back to where it
8675          belongs */
8676       if (AOP_SIZE (result) > 1 &&
8677           !OP_SYMBOL (left)->remat &&
8678           (OP_SYMBOL (left)->liveTo > ic->seq ||
8679            ic->depth))
8680         {
8681           int size = AOP_SIZE (result) - 1;
8682           while (size--)
8683             emitcode ("dec", "%s", rname);
8684         }
8685     }
8686
8687   /* done */
8688   freeAsmop (result, NULL, ic, TRUE);
8689
8690
8691 }
8692
8693 /*-----------------------------------------------------------------*/
8694 /* genFarPointerGet - gget value from far space                    */
8695 /*-----------------------------------------------------------------*/
8696 static void
8697 genFarPointerGet (operand * left,
8698                   operand * result, iCode * ic)
8699 {
8700   int size, offset;
8701   sym_link *retype = getSpec (operandType (result));
8702   sym_link *letype = getSpec (operandType (left));
8703   D (emitcode (";", "genFarPointerGet");
8704     );
8705
8706   aopOp (left, ic, FALSE, FALSE);
8707
8708   /* if the operand is already in dptr
8709      then we do nothing else we move the value to dptr */
8710   if (AOP_TYPE (left) != AOP_STR)
8711     {
8712       /* if this is remateriazable */
8713       if (AOP_TYPE (left) == AOP_IMMD)
8714         {
8715           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8716         }
8717       else
8718         {
8719           /* we need to get it byte by byte */
8720           _startLazyDPSEvaluation ();
8721           if (AOP_TYPE (left) != AOP_DPTR)
8722             {
8723               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8724               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8725               if (options.model == MODEL_FLAT24)
8726                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8727             }
8728           else
8729             {
8730               /* We need to generate a load to DPTR indirect through DPTR. */
8731               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8732                 );
8733               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8734               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8735               if (options.model == MODEL_FLAT24)
8736                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8737               emitcode ("pop", "dph");
8738               emitcode ("pop", "dpl");
8739             }
8740           _endLazyDPSEvaluation ();
8741         }
8742     }
8743   /* so dptr know contains the address */
8744   freeAsmop (left, NULL, ic, TRUE);
8745   aopOp (result, ic, FALSE, TRUE);
8746
8747   /* if bit then unpack */
8748   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8749     genUnpackBits (result, "dptr", FPOINTER);
8750   else
8751     {
8752       size = AOP_SIZE (result);
8753       offset = 0;
8754
8755       _startLazyDPSEvaluation ();
8756       while (size--)
8757         {
8758
8759           genSetDPTR (0);
8760           _flushLazyDPS ();
8761
8762           emitcode ("movx", "a,@dptr");
8763           if (size)
8764             emitcode ("inc", "dptr");
8765
8766           aopPut (AOP (result), "a", offset++);
8767         }
8768       _endLazyDPSEvaluation ();
8769     }
8770
8771   freeAsmop (result, NULL, ic, TRUE);
8772 }
8773
8774 /*-----------------------------------------------------------------*/
8775 /* emitcodePointerGet - gget value from code space                  */
8776 /*-----------------------------------------------------------------*/
8777 static void
8778 emitcodePointerGet (operand * left,
8779                     operand * result, iCode * ic)
8780 {
8781   int size, offset;
8782   sym_link *retype = getSpec (operandType (result));
8783
8784   aopOp (left, ic, FALSE, FALSE);
8785
8786   /* if the operand is already in dptr
8787      then we do nothing else we move the value to dptr */
8788   if (AOP_TYPE (left) != AOP_STR)
8789     {
8790       /* if this is remateriazable */
8791       if (AOP_TYPE (left) == AOP_IMMD)
8792         {
8793           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8794         }
8795       else
8796         {                       /* we need to get it byte by byte */
8797           _startLazyDPSEvaluation ();
8798           if (AOP_TYPE (left) != AOP_DPTR)
8799             {
8800               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8801               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8802               if (options.model == MODEL_FLAT24)
8803                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8804             }
8805           else
8806             {
8807               /* We need to generate a load to DPTR indirect through DPTR. */
8808               D (emitcode (";", "gencodePointerGet -- indirection special case.");
8809                 );
8810               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8811               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8812               if (options.model == MODEL_FLAT24)
8813                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8814               emitcode ("pop", "dph");
8815               emitcode ("pop", "dpl");
8816             }
8817           _endLazyDPSEvaluation ();
8818         }
8819     }
8820   /* so dptr know contains the address */
8821   freeAsmop (left, NULL, ic, TRUE);
8822   aopOp (result, ic, FALSE, TRUE);
8823
8824   /* if bit then unpack */
8825   if (IS_BITVAR (retype))
8826     genUnpackBits (result, "dptr", CPOINTER);
8827   else
8828     {
8829       size = AOP_SIZE (result);
8830       offset = 0;
8831
8832       _startLazyDPSEvaluation ();
8833       while (size--)
8834         {
8835           genSetDPTR (0);
8836           _flushLazyDPS ();
8837
8838           emitcode ("clr", "a");
8839           emitcode ("movc", "a,@a+dptr");
8840           if (size)
8841             emitcode ("inc", "dptr");
8842           aopPut (AOP (result), "a", offset++);
8843         }
8844       _endLazyDPSEvaluation ();
8845     }
8846
8847   freeAsmop (result, NULL, ic, TRUE);
8848 }
8849
8850 /*-----------------------------------------------------------------*/
8851 /* genGenPointerGet - gget value from generic pointer space        */
8852 /*-----------------------------------------------------------------*/
8853 static void
8854 genGenPointerGet (operand * left,
8855                   operand * result, iCode * ic)
8856 {
8857   int size, offset;
8858   sym_link *retype = getSpec (operandType (result));
8859   sym_link *letype = getSpec (operandType (left));
8860
8861   D (emitcode (";", "genGenPointerGet "); );
8862
8863   aopOp (left, ic, FALSE, TRUE);
8864
8865   /* if the operand is already in dptr
8866      then we do nothing else we move the value to dptr */
8867   if (AOP_TYPE (left) != AOP_STR)
8868     {
8869       /* if this is remateriazable */
8870       if (AOP_TYPE (left) == AOP_IMMD)
8871         {
8872           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8873           emitcode ("mov", "b,#%d", pointerCode (retype));
8874         }
8875       else
8876         {                       /* we need to get it byte by byte */
8877           _startLazyDPSEvaluation ();
8878           if (AOP(left)->type==AOP_DPTR2) {
8879             char *l;
8880             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8881             genSetDPTR(0);
8882             _flushLazyDPS();
8883             emitcode ("mov", "dpl,%s", l);
8884             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8885             genSetDPTR(0);
8886             _flushLazyDPS();
8887             emitcode ("mov", "dph,%s", l);
8888             if (options.model == MODEL_FLAT24) {
8889               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8890               genSetDPTR(0);
8891               _flushLazyDPS();
8892               emitcode ("mov", "dpx,%s", l);
8893               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8894             } else {
8895               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8896             }
8897           } else {
8898             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8899             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8900             if (options.model == MODEL_FLAT24) {
8901               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8902               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8903             } else {
8904               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8905             }
8906           }
8907           _endLazyDPSEvaluation ();
8908         }
8909     }
8910   /* so dptr know contains the address */
8911   freeAsmop (left, NULL, ic, TRUE);
8912   aopOp (result, ic, FALSE, TRUE);
8913
8914   /* if bit then unpack */
8915   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8916     genUnpackBits (result, "dptr", GPOINTER);
8917   else
8918     {
8919       size = AOP_SIZE (result);
8920       offset = 0;
8921
8922       while (size--)
8923         {
8924           emitcode ("lcall", "__gptrget");
8925           aopPut (AOP (result), "a", offset++);
8926           if (size)
8927             emitcode ("inc", "dptr");
8928         }
8929     }
8930
8931   freeAsmop (result, NULL, ic, TRUE);
8932 }
8933
8934 /*-----------------------------------------------------------------*/
8935 /* genPointerGet - generate code for pointer get                   */
8936 /*-----------------------------------------------------------------*/
8937 static void
8938 genPointerGet (iCode * ic)
8939 {
8940   operand *left, *result;
8941   sym_link *type, *etype;
8942   int p_type;
8943
8944   D (emitcode (";", "genPointerGet ");
8945     );
8946
8947   left = IC_LEFT (ic);
8948   result = IC_RESULT (ic);
8949
8950   /* depending on the type of pointer we need to
8951      move it to the correct pointer register */
8952   type = operandType (left);
8953   etype = getSpec (type);
8954   /* if left is of type of pointer then it is simple */
8955   if (IS_PTR (type) && !IS_FUNC (type->next))
8956     p_type = DCL_TYPE (type);
8957   else
8958     {
8959       /* we have to go by the storage class */
8960       p_type = PTR_TYPE (SPEC_OCLS (etype));
8961     }
8962
8963   /* now that we have the pointer type we assign
8964      the pointer values */
8965   switch (p_type)
8966     {
8967
8968     case POINTER:
8969     case IPOINTER:
8970       genNearPointerGet (left, result, ic);
8971       break;
8972
8973     case PPOINTER:
8974       genPagedPointerGet (left, result, ic);
8975       break;
8976
8977     case FPOINTER:
8978       genFarPointerGet (left, result, ic);
8979       break;
8980
8981     case CPOINTER:
8982       emitcodePointerGet (left, result, ic);
8983       break;
8984
8985     case GPOINTER:
8986       genGenPointerGet (left, result, ic);
8987       break;
8988     }
8989
8990 }
8991
8992 /*-----------------------------------------------------------------*/
8993 /* genPackBits - generates code for packed bit storage             */
8994 /*-----------------------------------------------------------------*/
8995 static void
8996 genPackBits (sym_link * etype,
8997              operand * right,
8998              char *rname, int p_type)
8999 {
9000   int shCount = 0;
9001   int offset = 0;
9002   int rLen = 0;
9003   int blen, bstr;
9004   char *l;
9005
9006   blen = SPEC_BLEN (etype);
9007   bstr = SPEC_BSTR (etype);
9008
9009   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9010   MOVA (l);
9011
9012   /* if the bit lenth is less than or    */
9013   /* it exactly fits a byte then         */
9014   if (SPEC_BLEN (etype) <= 8)
9015     {
9016       shCount = SPEC_BSTR (etype);
9017
9018       /* shift left acc */
9019       AccLsh (shCount);
9020
9021       if (SPEC_BLEN (etype) < 8)
9022         {                       /* if smaller than a byte */
9023
9024
9025           switch (p_type)
9026             {
9027             case POINTER:
9028               emitcode ("mov", "b,a");
9029               emitcode ("mov", "a,@%s", rname);
9030               break;
9031
9032             case FPOINTER:
9033               emitcode ("mov", "b,a");
9034               emitcode ("movx", "a,@dptr");
9035               break;
9036
9037             case GPOINTER:
9038               emitcode ("push", "b");
9039               emitcode ("push", "acc");
9040               emitcode ("lcall", "__gptrget");
9041               emitcode ("pop", "b");
9042               break;
9043             }
9044
9045           emitcode ("anl", "a,#0x%02x", (unsigned char)
9046                     ((unsigned char) (0xFF << (blen + bstr)) |
9047                      (unsigned char) (0xFF >> (8 - bstr))));
9048           emitcode ("orl", "a,b");
9049           if (p_type == GPOINTER)
9050             emitcode ("pop", "b");
9051         }
9052     }
9053
9054   switch (p_type)
9055     {
9056     case POINTER:
9057       emitcode ("mov", "@%s,a", rname);
9058       break;
9059
9060     case FPOINTER:
9061       emitcode ("movx", "@dptr,a");
9062       break;
9063
9064     case GPOINTER:
9065       emitcode ("lcall", "__gptrput");
9066       break;
9067     }
9068
9069   /* if we r done */
9070   if (SPEC_BLEN (etype) <= 8)
9071     return;
9072
9073   emitcode ("inc", "%s", rname);
9074   rLen = SPEC_BLEN (etype);
9075
9076   /* now generate for lengths greater than one byte */
9077   while (1)
9078     {
9079
9080       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9081
9082       rLen -= 8;
9083       if (rLen < 8)
9084         break;
9085
9086       switch (p_type)
9087         {
9088         case POINTER:
9089           if (*l == '@')
9090             {
9091               MOVA (l);
9092               emitcode ("mov", "@%s,a", rname);
9093             }
9094           else
9095             emitcode ("mov", "@%s,%s", rname, l);
9096           break;
9097
9098         case FPOINTER:
9099           MOVA (l);
9100           emitcode ("movx", "@dptr,a");
9101           break;
9102
9103         case GPOINTER:
9104           MOVA (l);
9105           emitcode ("lcall", "__gptrput");
9106           break;
9107         }
9108       emitcode ("inc", "%s", rname);
9109     }
9110
9111   MOVA (l);
9112
9113   /* last last was not complete */
9114   if (rLen)
9115     {
9116       /* save the byte & read byte */
9117       switch (p_type)
9118         {
9119         case POINTER:
9120           emitcode ("mov", "b,a");
9121           emitcode ("mov", "a,@%s", rname);
9122           break;
9123
9124         case FPOINTER:
9125           emitcode ("mov", "b,a");
9126           emitcode ("movx", "a,@dptr");
9127           break;
9128
9129         case GPOINTER:
9130           emitcode ("push", "b");
9131           emitcode ("push", "acc");
9132           emitcode ("lcall", "__gptrget");
9133           emitcode ("pop", "b");
9134           break;
9135         }
9136
9137       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9138       emitcode ("orl", "a,b");
9139     }
9140
9141   if (p_type == GPOINTER)
9142     emitcode ("pop", "b");
9143
9144   switch (p_type)
9145     {
9146
9147     case POINTER:
9148       emitcode ("mov", "@%s,a", rname);
9149       break;
9150
9151     case FPOINTER:
9152       emitcode ("movx", "@dptr,a");
9153       break;
9154
9155     case GPOINTER:
9156       emitcode ("lcall", "__gptrput");
9157       break;
9158     }
9159 }
9160 /*-----------------------------------------------------------------*/
9161 /* genDataPointerSet - remat pointer to data space                 */
9162 /*-----------------------------------------------------------------*/
9163 static void
9164 genDataPointerSet (operand * right,
9165                    operand * result,
9166                    iCode * ic)
9167 {
9168   int size, offset = 0;
9169   char *l, buffer[256];
9170
9171   aopOp (right, ic, FALSE, FALSE);
9172
9173   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9174   size = AOP_SIZE (right);
9175   while (size--)
9176     {
9177       if (offset)
9178         sprintf (buffer, "(%s + %d)", l + 1, offset);
9179       else
9180         sprintf (buffer, "%s", l + 1);
9181       emitcode ("mov", "%s,%s", buffer,
9182                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9183     }
9184
9185   freeAsmop (right, NULL, ic, TRUE);
9186   freeAsmop (result, NULL, ic, TRUE);
9187 }
9188
9189 /*-----------------------------------------------------------------*/
9190 /* genNearPointerSet - emitcode for near pointer put                */
9191 /*-----------------------------------------------------------------*/
9192 static void
9193 genNearPointerSet (operand * right,
9194                    operand * result,
9195                    iCode * ic)
9196 {
9197   asmop *aop = NULL;
9198   regs *preg = NULL;
9199   char *rname, *l;
9200   sym_link *retype, *letype;
9201   sym_link *ptype = operandType (result);
9202
9203   retype = getSpec (operandType (right));
9204   letype = getSpec (ptype);
9205
9206   aopOp (result, ic, FALSE, FALSE);
9207
9208   /* if the result is rematerializable &
9209      in data space & not a bit variable */
9210   if (AOP_TYPE (result) == AOP_IMMD &&
9211       DCL_TYPE (ptype) == POINTER &&
9212       !IS_BITVAR (retype) &&
9213       !IS_BITVAR (letype))
9214     {
9215       genDataPointerSet (right, result, ic);
9216       return;
9217     }
9218
9219   /* if the value is already in a pointer register
9220      then don't need anything more */
9221   if (!AOP_INPREG (AOP (result)))
9222     {
9223       /* otherwise get a free pointer register */
9224       aop = newAsmop (0);
9225       preg = getFreePtr (ic, &aop, FALSE);
9226       emitcode ("mov", "%s,%s",
9227                 preg->name,
9228                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9229       rname = preg->name;
9230     }
9231   else
9232     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9233
9234   freeAsmop (result, NULL, ic, TRUE);
9235   aopOp (right, ic, FALSE, FALSE);
9236
9237   /* if bitfield then unpack the bits */
9238   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9239     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9240   else
9241     {
9242       /* we have can just get the values */
9243       int size = AOP_SIZE (right);
9244       int offset = 0;
9245
9246       while (size--)
9247         {
9248           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9249           if (*l == '@')
9250             {
9251               MOVA (l);
9252               emitcode ("mov", "@%s,a", rname);
9253             }
9254           else
9255             emitcode ("mov", "@%s,%s", rname, l);
9256           if (size)
9257             emitcode ("inc", "%s", rname);
9258           offset++;
9259         }
9260     }
9261
9262   /* now some housekeeping stuff */
9263   if (aop)
9264     {
9265       /* we had to allocate for this iCode */
9266       freeAsmop (NULL, aop, ic, TRUE);
9267     }
9268   else
9269     {
9270       /* we did not allocate which means left
9271          already in a pointer register, then
9272          if size > 0 && this could be used again
9273          we have to point it back to where it
9274          belongs */
9275       if (AOP_SIZE (right) > 1 &&
9276           !OP_SYMBOL (result)->remat &&
9277           (OP_SYMBOL (result)->liveTo > ic->seq ||
9278            ic->depth))
9279         {
9280           int size = AOP_SIZE (right) - 1;
9281           while (size--)
9282             emitcode ("dec", "%s", rname);
9283         }
9284     }
9285
9286   /* done */
9287   freeAsmop (right, NULL, ic, TRUE);
9288
9289
9290 }
9291
9292 /*-----------------------------------------------------------------*/
9293 /* genPagedPointerSet - emitcode for Paged pointer put             */
9294 /*-----------------------------------------------------------------*/
9295 static void
9296 genPagedPointerSet (operand * right,
9297                     operand * result,
9298                     iCode * ic)
9299 {
9300   asmop *aop = NULL;
9301   regs *preg = NULL;
9302   char *rname, *l;
9303   sym_link *retype, *letype;
9304
9305   retype = getSpec (operandType (right));
9306   letype = getSpec (operandType (result));
9307
9308   aopOp (result, ic, FALSE, FALSE);
9309
9310   /* if the value is already in a pointer register
9311      then don't need anything more */
9312   if (!AOP_INPREG (AOP (result)))
9313     {
9314       /* otherwise get a free pointer register */
9315       aop = newAsmop (0);
9316       preg = getFreePtr (ic, &aop, FALSE);
9317       emitcode ("mov", "%s,%s",
9318                 preg->name,
9319                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9320       rname = preg->name;
9321     }
9322   else
9323     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9324
9325   freeAsmop (result, NULL, ic, TRUE);
9326   aopOp (right, ic, FALSE, FALSE);
9327
9328   /* if bitfield then unpack the bits */
9329   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9330     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9331   else
9332     {
9333       /* we have can just get the values */
9334       int size = AOP_SIZE (right);
9335       int offset = 0;
9336
9337       while (size--)
9338         {
9339           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9340
9341           MOVA (l);
9342           emitcode ("movx", "@%s,a", rname);
9343
9344           if (size)
9345             emitcode ("inc", "%s", rname);
9346
9347           offset++;
9348         }
9349     }
9350
9351   /* now some housekeeping stuff */
9352   if (aop)
9353     {
9354       /* we had to allocate for this iCode */
9355       freeAsmop (NULL, aop, ic, TRUE);
9356     }
9357   else
9358     {
9359       /* we did not allocate which means left
9360          already in a pointer register, then
9361          if size > 0 && this could be used again
9362          we have to point it back to where it
9363          belongs */
9364       if (AOP_SIZE (right) > 1 &&
9365           !OP_SYMBOL (result)->remat &&
9366           (OP_SYMBOL (result)->liveTo > ic->seq ||
9367            ic->depth))
9368         {
9369           int size = AOP_SIZE (right) - 1;
9370           while (size--)
9371             emitcode ("dec", "%s", rname);
9372         }
9373     }
9374
9375   /* done */
9376   freeAsmop (right, NULL, ic, TRUE);
9377
9378
9379 }
9380
9381 /*-----------------------------------------------------------------*/
9382 /* genFarPointerSet - set value from far space                     */
9383 /*-----------------------------------------------------------------*/
9384 static void
9385 genFarPointerSet (operand * right,
9386                   operand * result, iCode * ic)
9387 {
9388   int size, offset;
9389   sym_link *retype = getSpec (operandType (right));
9390   sym_link *letype = getSpec (operandType (result));
9391
9392   aopOp (result, ic, FALSE, FALSE);
9393
9394   /* if the operand is already in dptr
9395      then we do nothing else we move the value to dptr */
9396   if (AOP_TYPE (result) != AOP_STR)
9397     {
9398       /* if this is remateriazable */
9399       if (AOP_TYPE (result) == AOP_IMMD)
9400         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9401       else
9402         {
9403           /* we need to get it byte by byte */
9404           _startLazyDPSEvaluation ();
9405           if (AOP_TYPE (result) != AOP_DPTR)
9406             {
9407               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9408               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9409               if (options.model == MODEL_FLAT24)
9410                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9411             }
9412           else
9413             {
9414               /* We need to generate a load to DPTR indirect through DPTR. */
9415               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9416                 );
9417               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9418               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9419               if (options.model == MODEL_FLAT24)
9420                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9421               emitcode ("pop", "dph");
9422               emitcode ("pop", "dpl");
9423             }
9424           _endLazyDPSEvaluation ();
9425         }
9426     }
9427   /* so dptr know contains the address */
9428   freeAsmop (result, NULL, ic, TRUE);
9429   aopOp (right, ic, FALSE, TRUE);
9430
9431   /* if bit then unpack */
9432   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9433     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9434   else
9435     {
9436       size = AOP_SIZE (right);
9437       offset = 0;
9438
9439       _startLazyDPSEvaluation ();
9440       while (size--)
9441         {
9442           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9443           MOVA (l);
9444
9445           genSetDPTR (0);
9446           _flushLazyDPS ();
9447
9448           emitcode ("movx", "@dptr,a");
9449           if (size)
9450             emitcode ("inc", "dptr");
9451         }
9452       _endLazyDPSEvaluation ();
9453     }
9454
9455   freeAsmop (right, NULL, ic, TRUE);
9456 }
9457
9458 /*-----------------------------------------------------------------*/
9459 /* genGenPointerSet - set value from generic pointer space         */
9460 /*-----------------------------------------------------------------*/
9461 static void
9462 genGenPointerSet (operand * right,
9463                   operand * result, iCode * ic)
9464 {
9465   int size, offset;
9466   sym_link *retype = getSpec (operandType (right));
9467   sym_link *letype = getSpec (operandType (result));
9468
9469   aopOp (result, ic, FALSE, TRUE);
9470
9471   /* if the operand is already in dptr
9472      then we do nothing else we move the value to dptr */
9473   if (AOP_TYPE (result) != AOP_STR)
9474     {
9475       _startLazyDPSEvaluation ();
9476       /* if this is remateriazable */
9477       if (AOP_TYPE (result) == AOP_IMMD)
9478         {
9479           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9480           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9481         }
9482       else
9483         {                       /* we need to get it byte by byte */
9484           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9485           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9486           if (options.model == MODEL_FLAT24) {
9487             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9488             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9489           } else {
9490             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9491           }
9492         }
9493       _endLazyDPSEvaluation ();
9494     }
9495   /* so dptr know contains the address */
9496   freeAsmop (result, NULL, ic, TRUE);
9497   aopOp (right, ic, FALSE, TRUE);
9498
9499   /* if bit then unpack */
9500   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9501     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9502   else
9503     {
9504       size = AOP_SIZE (right);
9505       offset = 0;
9506
9507       _startLazyDPSEvaluation ();
9508       while (size--)
9509         {
9510           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9511           MOVA (l);
9512
9513           genSetDPTR (0);
9514           _flushLazyDPS ();
9515
9516           emitcode ("lcall", "__gptrput");
9517           if (size)
9518             emitcode ("inc", "dptr");
9519         }
9520       _endLazyDPSEvaluation ();
9521     }
9522
9523   freeAsmop (right, NULL, ic, TRUE);
9524 }
9525
9526 /*-----------------------------------------------------------------*/
9527 /* genPointerSet - stores the value into a pointer location        */
9528 /*-----------------------------------------------------------------*/
9529 static void
9530 genPointerSet (iCode * ic)
9531 {
9532   operand *right, *result;
9533   sym_link *type, *etype;
9534   int p_type;
9535
9536   D (emitcode (";", "genPointerSet ");
9537     );
9538
9539   right = IC_RIGHT (ic);
9540   result = IC_RESULT (ic);
9541
9542   /* depending on the type of pointer we need to
9543      move it to the correct pointer register */
9544   type = operandType (result);
9545   etype = getSpec (type);
9546   /* if left is of type of pointer then it is simple */
9547   if (IS_PTR (type) && !IS_FUNC (type->next))
9548     {
9549       p_type = DCL_TYPE (type);
9550     }
9551   else
9552     {
9553       /* we have to go by the storage class */
9554       p_type = PTR_TYPE (SPEC_OCLS (etype));
9555     }
9556
9557   /* now that we have the pointer type we assign
9558      the pointer values */
9559   switch (p_type)
9560     {
9561
9562     case POINTER:
9563     case IPOINTER:
9564       genNearPointerSet (right, result, ic);
9565       break;
9566
9567     case PPOINTER:
9568       genPagedPointerSet (right, result, ic);
9569       break;
9570
9571     case FPOINTER:
9572       genFarPointerSet (right, result, ic);
9573       break;
9574
9575     case GPOINTER:
9576       genGenPointerSet (right, result, ic);
9577       break;
9578     }
9579
9580 }
9581
9582 /*-----------------------------------------------------------------*/
9583 /* genIfx - generate code for Ifx statement                        */
9584 /*-----------------------------------------------------------------*/
9585 static void
9586 genIfx (iCode * ic, iCode * popIc)
9587 {
9588   operand *cond = IC_COND (ic);
9589   int isbit = 0;
9590
9591   D (emitcode (";", "genIfx "););
9592
9593   aopOp (cond, ic, FALSE, FALSE);
9594
9595   /* get the value into acc */
9596   if (AOP_TYPE (cond) != AOP_CRY)
9597     toBoolean (cond);
9598   else
9599     isbit = 1;
9600   /* the result is now in the accumulator */
9601   freeAsmop (cond, NULL, ic, TRUE);
9602
9603   /* if there was something to be popped then do it */
9604   if (popIc)
9605     genIpop (popIc);
9606
9607   /* if the condition is  a bit variable */
9608   if (isbit && IS_ITEMP (cond) &&
9609       SPIL_LOC (cond))
9610     genIfxJump (ic, SPIL_LOC (cond)->rname);
9611   else if (isbit && !IS_ITEMP (cond))
9612     genIfxJump (ic, OP_SYMBOL (cond)->rname);
9613   else
9614     genIfxJump (ic, "a");
9615
9616   ic->generated = 1;
9617 }
9618
9619 /*-----------------------------------------------------------------*/
9620 /* genAddrOf - generates code for address of                       */
9621 /*-----------------------------------------------------------------*/
9622 static void
9623 genAddrOf (iCode * ic)
9624 {
9625   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9626   int size, offset;
9627
9628   D (emitcode (";", "genAddrOf ");
9629     );
9630
9631   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9632
9633   /* if the operand is on the stack then we
9634      need to get the stack offset of this
9635      variable */
9636   if (sym->onStack)
9637     {
9638       /* if it has an offset then we need to compute
9639          it */
9640       if (sym->stack)
9641         {
9642           emitcode ("mov", "a,_bp");
9643           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9644           aopPut (AOP (IC_RESULT (ic)), "a", 0);
9645         }
9646       else
9647         {
9648           /* we can just move _bp */
9649           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9650         }
9651       /* fill the result with zero */
9652       size = AOP_SIZE (IC_RESULT (ic)) - 1;
9653
9654
9655       if (options.stack10bit && size < (FPTRSIZE - 1))
9656         {
9657           fprintf (stderr,
9658                    "*** warning: pointer to stack var truncated.\n");
9659         }
9660
9661       offset = 1;
9662       while (size--)
9663         {
9664           /* Yuck! */
9665           if (options.stack10bit && offset == 2)
9666             {
9667               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9668             }
9669           else
9670             {
9671               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9672             }
9673         }
9674
9675       goto release;
9676     }
9677
9678   /* object not on stack then we need the name */
9679   size = AOP_SIZE (IC_RESULT (ic));
9680   offset = 0;
9681
9682   while (size--)
9683     {
9684       char s[SDCC_NAME_MAX];
9685       if (offset)
9686         sprintf (s, "#(%s >> %d)",
9687                  sym->rname,
9688                  offset * 8);
9689       else
9690         sprintf (s, "#%s", sym->rname);
9691       aopPut (AOP (IC_RESULT (ic)), s, offset++);
9692     }
9693
9694 release:
9695   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9696
9697 }
9698
9699 /*-----------------------------------------------------------------*/
9700 /* genArrayInit - generates code for address of                       */
9701 /*-----------------------------------------------------------------*/
9702 static void
9703 genArrayInit (iCode * ic)
9704 {
9705     literalList *iLoop;
9706     int         ix, count;
9707     int         elementSize = 0, eIndex;
9708     unsigned    val, lastVal;
9709     sym_link    *type;
9710     operand     *left=IC_LEFT(ic);
9711     
9712     D (emitcode (";", "genArrayInit "););
9713
9714     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9715     
9716     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9717     {
9718         // Load immediate value into DPTR.
9719         emitcode("mov", "dptr, %s",
9720              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9721     }
9722     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9723     {
9724 #if 0
9725       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9726               "Unexpected operand to genArrayInit.\n");
9727       exit(1);
9728 #else
9729       // a regression because of SDCCcse.c:1.52
9730       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9731       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9732       if (options.model == MODEL_FLAT24)
9733         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9734 #endif
9735     }
9736     
9737     type = operandType(IC_LEFT(ic));
9738     
9739     if (type && type->next)
9740     {
9741         elementSize = getSize(type->next);
9742     }
9743     else
9744     {
9745         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9746                                 "can't determine element size in genArrayInit.\n");
9747         exit(1);
9748     }
9749     
9750     iLoop = IC_ARRAYILIST(ic);
9751     lastVal = 0xffff;
9752     
9753     while (iLoop)
9754     {
9755         bool firstpass = TRUE;
9756         
9757         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
9758                  iLoop->count, (int)iLoop->literalValue, elementSize);
9759         
9760         ix = iLoop->count;
9761         
9762         while (ix)
9763         {
9764             symbol *tlbl = NULL;
9765             
9766             count = ix > 256 ? 256 : ix;
9767             
9768             if (count > 1)
9769             {
9770                 tlbl = newiTempLabel (NULL);
9771                 if (firstpass || (count & 0xff))
9772                 {
9773                     emitcode("mov", "b, #0x%x", count & 0xff);
9774                 }
9775                 
9776                 emitcode ("", "%05d$:", tlbl->key + 100);
9777             }
9778             
9779             firstpass = FALSE;
9780                 
9781             for (eIndex = 0; eIndex < elementSize; eIndex++)
9782             {
9783                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9784                 if (val != lastVal)
9785                 {
9786                     emitcode("mov", "a, #0x%x", val);
9787                     lastVal = val;
9788                 }
9789                 
9790                 emitcode("movx", "@dptr, a");
9791                 emitcode("inc", "dptr");
9792             }
9793             
9794             if (count > 1)
9795             {
9796                 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9797             }
9798             
9799             ix -= count;
9800         }
9801         
9802         iLoop = iLoop->next;
9803     }
9804     
9805     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9806 }
9807
9808 /*-----------------------------------------------------------------*/
9809 /* genFarFarAssign - assignment when both are in far space         */
9810 /*-----------------------------------------------------------------*/
9811 static void
9812 genFarFarAssign (operand * result, operand * right, iCode * ic)
9813 {
9814   int size = AOP_SIZE (right);
9815   int offset = 0;
9816   symbol *rSym = NULL;
9817
9818   if (size == 1)
9819   {
9820       /* quick & easy case. */
9821       D(emitcode(";","genFarFarAssign (1 byte case)"););      
9822       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9823       freeAsmop (right, NULL, ic, FALSE);
9824       /* now assign DPTR to result */
9825       _G.accInUse++;
9826       aopOp(result, ic, FALSE, FALSE);
9827       _G.accInUse--;
9828       aopPut(AOP(result), "a", 0);
9829       freeAsmop(result, NULL, ic, FALSE);
9830       return;
9831   }
9832   
9833   /* See if we've got an underlying symbol to abuse. */
9834   if (IS_SYMOP(result) && OP_SYMBOL(result))
9835   {
9836       if (IS_TRUE_SYMOP(result))
9837       {
9838           rSym = OP_SYMBOL(result);
9839       }
9840       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9841       {
9842           rSym = OP_SYMBOL(result)->usl.spillLoc;
9843       }
9844   }
9845              
9846   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9847   {
9848       /* We can use the '390 auto-toggle feature to good effect here. */
9849       
9850       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9851       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
9852       emitcode ("mov", "dptr,#%s", rSym->rname); 
9853       /* DP2 = result, DP1 = right, DP1 is current. */
9854       while (size)
9855       {
9856           emitcode("movx", "a,@dptr");
9857           emitcode("movx", "@dptr,a");
9858           if (--size)
9859           {
9860                emitcode("inc", "dptr");
9861                emitcode("inc", "dptr");
9862           }
9863       }
9864       emitcode("mov", "dps, #0");
9865       freeAsmop (right, NULL, ic, FALSE);
9866 #if 0
9867 some alternative code for processors without auto-toggle
9868 no time to test now, so later well put in...kpb
9869         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9870         emitcode("mov", "dps, #0x01");  /* Select DPTR2. */
9871         emitcode ("mov", "dptr,#%s", rSym->rname); 
9872         /* DP2 = result, DP1 = right, DP1 is current. */
9873         while (size)
9874         {
9875           --size;
9876           emitcode("movx", "a,@dptr");
9877           if (size)
9878             emitcode("inc", "dptr");
9879           emitcode("inc", "dps");
9880           emitcode("movx", "@dptr,a");
9881           if (size)
9882             emitcode("inc", "dptr");
9883           emitcode("inc", "dps");
9884         }
9885         emitcode("mov", "dps, #0");
9886         freeAsmop (right, NULL, ic, FALSE);
9887 #endif
9888   }
9889   else
9890   {
9891       D (emitcode (";", "genFarFarAssign"););
9892       aopOp (result, ic, TRUE, TRUE);
9893
9894       _startLazyDPSEvaluation ();
9895       
9896       while (size--)
9897         {
9898           aopPut (AOP (result),
9899                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9900           offset++;
9901         }
9902       _endLazyDPSEvaluation ();
9903       freeAsmop (result, NULL, ic, FALSE);
9904       freeAsmop (right, NULL, ic, FALSE);
9905   }
9906 }
9907
9908 /*-----------------------------------------------------------------*/
9909 /* genAssign - generate code for assignment                        */
9910 /*-----------------------------------------------------------------*/
9911 static void
9912 genAssign (iCode * ic)
9913 {
9914   operand *result, *right;
9915   int size, offset;
9916   unsigned long lit = 0L;
9917
9918   D (emitcode (";", "genAssign ");
9919     );
9920
9921   result = IC_RESULT (ic);
9922   right = IC_RIGHT (ic);
9923
9924   /* if they are the same */
9925   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9926     return;
9927
9928   aopOp (right, ic, FALSE, FALSE);
9929
9930   emitcode (";", "genAssign: resultIsFar = %s",
9931             isOperandInFarSpace (result) ?
9932             "TRUE" : "FALSE");
9933
9934   /* special case both in far space */
9935   if ((AOP_TYPE (right) == AOP_DPTR ||
9936        AOP_TYPE (right) == AOP_DPTR2) &&
9937   /* IS_TRUE_SYMOP(result)       && */
9938       isOperandInFarSpace (result))
9939     {
9940       genFarFarAssign (result, right, ic);
9941       return;
9942     }
9943
9944   aopOp (result, ic, TRUE, FALSE);
9945
9946   /* if they are the same registers */
9947   if (sameRegs (AOP (right), AOP (result)))
9948     goto release;
9949
9950   /* if the result is a bit */
9951   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9952     {
9953       /* if the right size is a literal then
9954          we know what the value is */
9955       if (AOP_TYPE (right) == AOP_LIT)
9956         {
9957           if (((int) operandLitValue (right)))
9958             aopPut (AOP (result), one, 0);
9959           else
9960             aopPut (AOP (result), zero, 0);
9961           goto release;
9962         }
9963
9964       /* the right is also a bit variable */
9965       if (AOP_TYPE (right) == AOP_CRY)
9966         {
9967           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9968           aopPut (AOP (result), "c", 0);
9969           goto release;
9970         }
9971
9972       /* we need to or */
9973       toBoolean (right);
9974       aopPut (AOP (result), "a", 0);
9975       goto release;
9976     }
9977
9978   /* bit variables done */
9979   /* general case */
9980   size = AOP_SIZE (result);
9981   offset = 0;
9982   if (AOP_TYPE (right) == AOP_LIT)
9983     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9984
9985   if ((size > 1) &&
9986       (AOP_TYPE (result) != AOP_REG) &&
9987       (AOP_TYPE (right) == AOP_LIT) &&
9988       !IS_FLOAT (operandType (right)))
9989     {
9990       _startLazyDPSEvaluation ();
9991       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9992         {
9993           aopPut (AOP (result),
9994                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9995                   offset);
9996           offset++;
9997           size--;
9998         }
9999       /* And now fill the rest with zeros. */
10000       if (size)
10001         {
10002           emitcode ("clr", "a");
10003         }
10004       while (size--)
10005         {
10006           aopPut (AOP (result), "a", offset++);
10007         }
10008       _endLazyDPSEvaluation ();
10009     }
10010   else
10011     {
10012       _startLazyDPSEvaluation ();
10013       while (size--)
10014         {
10015           aopPut (AOP (result),
10016                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10017                   offset);
10018           offset++;
10019         }
10020       _endLazyDPSEvaluation ();
10021     }
10022
10023 release:
10024   freeAsmop (right, NULL, ic, FALSE);
10025   freeAsmop (result, NULL, ic, TRUE);
10026 }
10027
10028 /*-----------------------------------------------------------------*/
10029 /* genJumpTab - generates code for jump table                      */
10030 /*-----------------------------------------------------------------*/
10031 static void
10032 genJumpTab (iCode * ic)
10033 {
10034   symbol *jtab;
10035   char *l;
10036
10037   D (emitcode (";", "genJumpTab ");
10038     );
10039
10040   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10041   /* get the condition into accumulator */
10042   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10043   MOVA (l);
10044   /* multiply by four! */
10045   emitcode ("add", "a,acc");
10046   emitcode ("add", "a,acc");
10047   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10048
10049   jtab = newiTempLabel (NULL);
10050   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10051   emitcode ("jmp", "@a+dptr");
10052   emitcode ("", "%05d$:", jtab->key + 100);
10053   /* now generate the jump labels */
10054   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10055        jtab = setNextItem (IC_JTLABELS (ic)))
10056     emitcode ("ljmp", "%05d$", jtab->key + 100);
10057
10058 }
10059
10060 /*-----------------------------------------------------------------*/
10061 /* genCast - gen code for casting                                  */
10062 /*-----------------------------------------------------------------*/
10063 static void
10064 genCast (iCode * ic)
10065 {
10066   operand *result = IC_RESULT (ic);
10067   sym_link *ctype = operandType (IC_LEFT (ic));
10068   sym_link *rtype = operandType (IC_RIGHT (ic));
10069   operand *right = IC_RIGHT (ic);
10070   int size, offset;
10071
10072   D (emitcode (";", "genCast ");
10073     );
10074
10075   /* if they are equivalent then do nothing */
10076   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10077     return;
10078
10079   aopOp (right, ic, FALSE, FALSE);
10080   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10081
10082   /* if the result is a bit */
10083   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10084   if (IS_BITVAR(OP_SYMBOL(result)->type))
10085     {
10086       /* if the right size is a literal then
10087          we know what the value is */
10088       if (AOP_TYPE (right) == AOP_LIT)
10089         {
10090           if (((int) operandLitValue (right)))
10091             aopPut (AOP (result), one, 0);
10092           else
10093             aopPut (AOP (result), zero, 0);
10094
10095           goto release;
10096         }
10097
10098       /* the right is also a bit variable */
10099       if (AOP_TYPE (right) == AOP_CRY)
10100         {
10101           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10102           aopPut (AOP (result), "c", 0);
10103           goto release;
10104         }
10105
10106       /* we need to or */
10107       toBoolean (right);
10108       aopPut (AOP (result), "a", 0);
10109       goto release;
10110     }
10111
10112   /* if they are the same size : or less */
10113   if (AOP_SIZE (result) <= AOP_SIZE (right))
10114     {
10115
10116       /* if they are in the same place */
10117       if (sameRegs (AOP (right), AOP (result)))
10118         goto release;
10119
10120       /* if they in different places then copy */
10121       size = AOP_SIZE (result);
10122       offset = 0;
10123       _startLazyDPSEvaluation ();
10124       while (size--)
10125         {
10126           aopPut (AOP (result),
10127                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10128                   offset);
10129           offset++;
10130         }
10131       _endLazyDPSEvaluation ();
10132       goto release;
10133     }
10134
10135
10136   /* if the result is of type pointer */
10137   if (IS_PTR (ctype))
10138     {
10139
10140       int p_type;
10141       sym_link *type = operandType (right);
10142
10143       /* pointer to generic pointer */
10144       if (IS_GENPTR (ctype))
10145         {
10146           char *l = zero;
10147
10148           if (IS_PTR (type))
10149             {
10150               p_type = DCL_TYPE (type);
10151             }
10152           else
10153             {
10154 #if OLD_CAST_BEHAVIOR
10155               /* KV: we are converting a non-pointer type to
10156                * a generic pointer. This (ifdef'd out) code
10157                * says that the resulting generic pointer
10158                * should have the same class as the storage
10159                * location of the non-pointer variable.
10160                *
10161                * For example, converting an int (which happens
10162                * to be stored in DATA space) to a pointer results
10163                * in a DATA generic pointer; if the original int
10164                * in XDATA space, so will be the resulting pointer.
10165                *
10166                * I don't like that behavior, and thus this change:
10167                * all such conversions will be forced to XDATA and
10168                * throw a warning. If you want some non-XDATA
10169                * type, or you want to suppress the warning, you
10170                * must go through an intermediate cast, like so:
10171                *
10172                * char _generic *gp = (char _xdata *)(intVar);
10173                */
10174               sym_link *etype = getSpec (type);
10175
10176               /* we have to go by the storage class */
10177               if (SPEC_OCLS (etype) != generic)
10178                 {
10179                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10180                 }
10181               else
10182 #endif
10183                 {
10184                   /* Converting unknown class (i.e. register variable)
10185                    * to generic pointer. This is not good, but
10186                    * we'll make a guess (and throw a warning).
10187                    */
10188                   p_type = FPOINTER;
10189                   werror (W_INT_TO_GEN_PTR_CAST);
10190                 }
10191             }
10192
10193           /* the first two bytes are known */
10194           size = GPTRSIZE - 1;
10195           offset = 0;
10196           _startLazyDPSEvaluation ();
10197           while (size--)
10198             {
10199               aopPut (AOP (result),
10200                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10201                       offset);
10202               offset++;
10203             }
10204           _endLazyDPSEvaluation ();
10205
10206           /* the last byte depending on type */
10207           switch (p_type)
10208             {
10209             case IPOINTER:
10210             case POINTER:
10211               l = zero;
10212               break;
10213             case FPOINTER:
10214               l = one;
10215               break;
10216             case CPOINTER:
10217               l = "#0x02";
10218               break;
10219             case PPOINTER:
10220               l = "#0x03";
10221               break;
10222
10223             default:
10224               /* this should never happen */
10225               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10226                       "got unknown pointer type");
10227               exit (1);
10228             }
10229           aopPut (AOP (result), l, GPTRSIZE - 1);
10230           goto release;
10231         }
10232
10233       /* just copy the pointers */
10234       size = AOP_SIZE (result);
10235       offset = 0;
10236       _startLazyDPSEvaluation ();
10237       while (size--)
10238         {
10239           aopPut (AOP (result),
10240                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10241                   offset);
10242           offset++;
10243         }
10244       _endLazyDPSEvaluation ();
10245       goto release;
10246     }
10247
10248   /* so we now know that the size of destination is greater
10249      than the size of the source */
10250   /* we move to result for the size of source */
10251   size = AOP_SIZE (right);
10252   offset = 0;
10253   _startLazyDPSEvaluation ();
10254   while (size--)
10255     {
10256       aopPut (AOP (result),
10257               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10258               offset);
10259       offset++;
10260     }
10261   _endLazyDPSEvaluation ();
10262
10263   /* now depending on the sign of the source && destination */
10264   size = AOP_SIZE (result) - AOP_SIZE (right);
10265   /* if unsigned or not an integral type */
10266   /* also, if the source is a bit, we don't need to sign extend, because
10267    * it can't possibly have set the sign bit.
10268    */
10269   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10270     {
10271       while (size--)
10272         {
10273           aopPut (AOP (result), zero, offset++);
10274         }
10275     }
10276   else
10277     {
10278       /* we need to extend the sign :{ */
10279       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10280                         FALSE, FALSE, TRUE);
10281       MOVA (l);
10282       emitcode ("rlc", "a");
10283       emitcode ("subb", "a,acc");
10284       while (size--)
10285         aopPut (AOP (result), "a", offset++);
10286     }
10287
10288   /* we are done hurray !!!! */
10289
10290 release:
10291   freeAsmop (right, NULL, ic, TRUE);
10292   freeAsmop (result, NULL, ic, TRUE);
10293
10294 }
10295
10296 /*-----------------------------------------------------------------*/
10297 /* genDjnz - generate decrement & jump if not zero instrucion      */
10298 /*-----------------------------------------------------------------*/
10299 static int
10300 genDjnz (iCode * ic, iCode * ifx)
10301 {
10302   symbol *lbl, *lbl1;
10303   if (!ifx)
10304     return 0;
10305
10306   /* if the if condition has a false label
10307      then we cannot save */
10308   if (IC_FALSE (ifx))
10309     return 0;
10310
10311   /* if the minus is not of the form
10312      a = a - 1 */
10313   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10314       !IS_OP_LITERAL (IC_RIGHT (ic)))
10315     return 0;
10316
10317   if (operandLitValue (IC_RIGHT (ic)) != 1)
10318     return 0;
10319
10320   /* if the size of this greater than one then no
10321      saving */
10322   if (getSize (operandType (IC_RESULT (ic))) > 1)
10323     return 0;
10324
10325   /* otherwise we can save BIG */
10326   D(emitcode(";", "genDjnz"););
10327
10328   lbl = newiTempLabel (NULL);
10329   lbl1 = newiTempLabel (NULL);
10330
10331   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10332
10333   if (AOP_NEEDSACC(IC_RESULT(ic)))
10334   {
10335       /* If the result is accessed indirectly via
10336        * the accumulator, we must explicitly write
10337        * it back after the decrement.
10338        */
10339       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10340       
10341       if (strcmp(rByte, "a"))
10342       {
10343            /* Something is hopelessly wrong */
10344            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10345                    __FILE__, __LINE__);
10346            /* We can just give up; the generated code will be inefficient,
10347             * but what the hey.
10348             */
10349            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10350            return 0;
10351       }
10352       emitcode ("dec", "%s", rByte);
10353       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10354       emitcode ("jnz", "%05d$", lbl->key + 100);
10355   }
10356   else if (IS_AOP_PREG (IC_RESULT (ic)))
10357     {
10358       emitcode ("dec", "%s",
10359                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10360       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10361       emitcode ("jnz", "%05d$", lbl->key + 100);
10362     }
10363   else
10364     {
10365       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10366                 lbl->key + 100);
10367     }
10368   emitcode ("sjmp", "%05d$", lbl1->key + 100);
10369   emitcode ("", "%05d$:", lbl->key + 100);
10370   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10371   emitcode ("", "%05d$:", lbl1->key + 100);
10372
10373   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10374   ifx->generated = 1;
10375   return 1;
10376 }
10377
10378 /*-----------------------------------------------------------------*/
10379 /* genReceive - generate code for a receive iCode                  */
10380 /*-----------------------------------------------------------------*/
10381 static void
10382 genReceive (iCode * ic)
10383 {
10384
10385   D (emitcode (";", "genReceive ");
10386     );
10387
10388   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10389       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10390        IS_TRUE_SYMOP (IC_RESULT (ic))))
10391     {
10392       int size = getSize (operandType (IC_RESULT (ic)));
10393       int offset = fReturnSizeDS390 - size;
10394       while (size--)
10395         {
10396           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10397                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10398           offset++;
10399         }
10400       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10401       size = AOP_SIZE (IC_RESULT (ic));
10402       offset = 0;
10403       while (size--)
10404         {
10405           emitcode ("pop", "acc");
10406           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10407         }
10408
10409     }
10410   else
10411     {
10412       _G.accInUse++;
10413       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10414       _G.accInUse--;
10415       assignResultValue (IC_RESULT (ic));
10416     }
10417
10418   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10419 }
10420
10421 /*-----------------------------------------------------------------*/
10422 /* gen390Code - generate code for Dallas 390 based controllers     */
10423 /*-----------------------------------------------------------------*/
10424 void
10425 gen390Code (iCode * lic)
10426 {
10427   iCode *ic;
10428   int cln = 0;
10429
10430   lineHead = lineCurr = NULL;
10431
10432   if (options.model == MODEL_FLAT24) {
10433     fReturnSizeDS390 = 5;
10434     fReturn = fReturn24;
10435   } else {
10436     fReturnSizeDS390 = 4;
10437     fReturn = fReturn16;
10438     options.stack10bit=0;
10439   }
10440 #if 0
10441   //REMOVE ME!!!
10442   /* print the allocation information */
10443   if (allocInfo)
10444     printAllocInfo (currFunc, codeOutFile);
10445 #endif
10446   /* if debug information required */
10447   if (options.debug && currFunc)
10448     {
10449       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10450       _G.debugLine = 1;
10451       if (IS_STATIC (currFunc->etype))
10452         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10453       else
10454         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10455       _G.debugLine = 0;
10456     }
10457   /* stack pointer name */
10458   if (options.useXstack)
10459     spname = "_spx";
10460   else
10461     spname = "sp";
10462
10463
10464   for (ic = lic; ic; ic = ic->next)
10465     {
10466
10467       if (cln != ic->lineno)
10468         {
10469           if (options.debug)
10470             {
10471               _G.debugLine = 1;
10472               emitcode ("", "C$%s$%d$%d$%d ==.",
10473                         FileBaseName (ic->filename), ic->lineno,
10474                         ic->level, ic->block);
10475               _G.debugLine = 0;
10476             }
10477           emitcode (";", "%s %d", ic->filename, ic->lineno);
10478           cln = ic->lineno;
10479         }
10480       /* if the result is marked as
10481          spilt and rematerializable or code for
10482          this has already been generated then
10483          do nothing */
10484       if (resultRemat (ic) || ic->generated)
10485         continue;
10486
10487       /* depending on the operation */
10488       switch (ic->op)
10489         {
10490         case '!':
10491           genNot (ic);
10492           break;
10493
10494         case '~':
10495           genCpl (ic);
10496           break;
10497
10498         case UNARYMINUS:
10499           genUminus (ic);
10500           break;
10501
10502         case IPUSH:
10503           genIpush (ic);
10504           break;
10505
10506         case IPOP:
10507           /* IPOP happens only when trying to restore a
10508              spilt live range, if there is an ifx statement
10509              following this pop then the if statement might
10510              be using some of the registers being popped which
10511              would destory the contents of the register so
10512              we need to check for this condition and handle it */
10513           if (ic->next &&
10514               ic->next->op == IFX &&
10515               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10516             genIfx (ic->next, ic);
10517           else
10518             genIpop (ic);
10519           break;
10520
10521         case CALL:
10522           genCall (ic);
10523           break;
10524
10525         case PCALL:
10526           genPcall (ic);
10527           break;
10528
10529         case FUNCTION:
10530           genFunction (ic);
10531           break;
10532
10533         case ENDFUNCTION:
10534           genEndFunction (ic);
10535           break;
10536
10537         case RETURN:
10538           genRet (ic);
10539           break;
10540
10541         case LABEL:
10542           genLabel (ic);
10543           break;
10544
10545         case GOTO:
10546           genGoto (ic);
10547           break;
10548
10549         case '+':
10550           genPlus (ic);
10551           break;
10552
10553         case '-':
10554           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10555             genMinus (ic);
10556           break;
10557
10558         case '*':
10559           genMult (ic);
10560           break;
10561
10562         case '/':
10563           genDiv (ic);
10564           break;
10565
10566         case '%':
10567           genMod (ic);
10568           break;
10569
10570         case '>':
10571           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10572           break;
10573
10574         case '<':
10575           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10576           break;
10577
10578         case LE_OP:
10579         case GE_OP:
10580         case NE_OP:
10581
10582           /* note these two are xlated by algebraic equivalence
10583              during parsing SDCC.y */
10584           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10585                   "got '>=' or '<=' shouldn't have come here");
10586           break;
10587
10588         case EQ_OP:
10589           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10590           break;
10591
10592         case AND_OP:
10593           genAndOp (ic);
10594           break;
10595
10596         case OR_OP:
10597           genOrOp (ic);
10598           break;
10599
10600         case '^':
10601           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10602           break;
10603
10604         case '|':
10605           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10606           break;
10607
10608         case BITWISEAND:
10609           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10610           break;
10611
10612         case INLINEASM:
10613           genInline (ic);
10614           break;
10615
10616         case RRC:
10617           genRRC (ic);
10618           break;
10619
10620         case RLC:
10621           genRLC (ic);
10622           break;
10623
10624         case GETHBIT:
10625           genGetHbit (ic);
10626           break;
10627
10628         case LEFT_OP:
10629           genLeftShift (ic);
10630           break;
10631
10632         case RIGHT_OP:
10633           genRightShift (ic);
10634           break;
10635
10636         case GET_VALUE_AT_ADDRESS:
10637           genPointerGet (ic);
10638           break;
10639
10640         case '=':
10641           if (POINTER_SET (ic))
10642             genPointerSet (ic);
10643           else
10644             genAssign (ic);
10645           break;
10646
10647         case IFX:
10648           genIfx (ic, NULL);
10649           break;
10650
10651         case ADDRESS_OF:
10652           genAddrOf (ic);
10653           break;
10654
10655         case JUMPTABLE:
10656           genJumpTab (ic);
10657           break;
10658
10659         case CAST:
10660           genCast (ic);
10661           break;
10662
10663         case RECEIVE:
10664           genReceive (ic);
10665           break;
10666
10667         case SEND:
10668           addSet (&_G.sendSet, ic);
10669           break;
10670
10671         case ARRAYINIT:
10672             genArrayInit(ic);
10673             break;
10674             
10675         default:
10676           ic = ic;
10677         }
10678     }
10679
10680
10681   /* now we are ready to call the
10682      peep hole optimizer */
10683   if (!options.nopeep)
10684     peepHole (&lineHead);
10685
10686   /* now do the actual printing */
10687   printLine (lineHead, codeOutFile);
10688   return;
10689 }