Bug 471076 fix
[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
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31
32 #include <common.h>
33 #include "ralloc.h"
34 #include "gen.h"
35 #include "SDCCglobl.h"
36 #include "newalloc.h"
37
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
40 #else
41 #ifdef HAVE_MACHINE_ENDIAN_H
42 #include <machine/endian.h>
43 #else
44 #ifdef HAVE_ENDIAN_H
45 #include <endian.h>
46 #else
47 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
48 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
49 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
50 #endif
51 #endif
52 #endif
53 #endif
54
55 #define BETTER_LITERAL_SHIFT
56
57 char *aopLiteral (value * val, int offset);
58
59 /* this is the down and dirty file with all kinds of
60    kludgy & hacky stuff. This is what it is all about
61    CODE GENERATION for a specific MCU . some of the
62    routines may be reusable, will have to see */
63
64 static char *zero = "#0x00";
65 static char *one = "#0x01";
66 static char *spname;
67
68 #define D(x) x
69
70 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
71 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
72
73 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
74 static char *fReturn24[] =
75 {"dpl", "dph", "dpx", "b", "a"};
76 static char *fReturn16[] =
77 {"dpl", "dph", "b", "a"};
78 static char **fReturn = fReturn24;
79 static char *accUse[] =
80 {"a", "b"};
81
82 static short rbank = -1;
83
84 static struct
85   {
86     short r0Pushed;
87     short r1Pushed;
88     short accInUse;
89     short inLine;
90     short debugLine;
91     short nRegsSaved;
92     set *sendSet;
93   }
94 _G;
95
96 static void saveRBank (int, iCode *, bool);
97
98 #define RESULTONSTACK(x) \
99                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
100                          IC_RESULT(x)->aop->type == AOP_STK )
101
102 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
103 #define MOVA(x) { char *_mova_tmp = strdup(x); \
104                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
105                  { \
106                     emitcode("mov","a,%s",_mova_tmp); \
107                  } \
108                  free(_mova_tmp); \
109                 }
110 #define CLRC    emitcode("clr","c")
111 #define SETC    emitcode("setb","c")
112
113 // A scratch register which will be used to hold
114 // result bytes from operands in far space via DPTR2.
115 #define DP2_RESULT_REG  "ap"
116
117 static lineNode *lineHead = NULL;
118 static lineNode *lineCurr = NULL;
119
120 static unsigned char SLMask[] =
121 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
122  0xE0, 0xC0, 0x80, 0x00};
123 static unsigned char SRMask[] =
124 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
125  0x07, 0x03, 0x01, 0x00};
126
127 #define LSB     0
128 #define MSB16   1
129 #define MSB24   2
130 #define MSB32   3
131
132 /*-----------------------------------------------------------------*/
133 /* emitcode - writes the code into a file : for now it is simple    */
134 /*-----------------------------------------------------------------*/
135 static void
136 emitcode (char *inst, char *fmt,...)
137 {
138   va_list ap;
139   char lb[INITIAL_INLINEASM];
140   char *lbp = lb;
141
142   va_start (ap, fmt);
143
144   if (inst && *inst)
145     {
146       if (fmt && *fmt)
147         sprintf (lb, "%s\t", inst);
148       else
149         sprintf (lb, "%s", inst);
150       vsprintf (lb + (strlen (lb)), fmt, ap);
151     }
152   else
153     vsprintf (lb, fmt, ap);
154
155   while (isspace (*lbp))
156     lbp++;
157
158   if (lbp && *lbp)
159     lineCurr = (lineCurr ?
160                 connectLine (lineCurr, newLineNode (lb)) :
161                 (lineHead = newLineNode (lb)));
162   lineCurr->isInline = _G.inLine;
163   lineCurr->isDebug = _G.debugLine;
164   va_end (ap);
165 }
166
167 /*-----------------------------------------------------------------*/
168 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
169 /*-----------------------------------------------------------------*/
170 static regs *
171 getFreePtr (iCode * ic, asmop ** aopp, bool result)
172 {
173   bool r0iu = FALSE, r1iu = FALSE;
174   bool r0ou = FALSE, r1ou = FALSE;
175
176   /* the logic: if r0 & r1 used in the instruction
177      then we are in trouble otherwise */
178
179   /* first check if r0 & r1 are used by this
180      instruction, in which case we are in trouble */
181   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
182   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
183   if (r0iu && r1iu) {
184       goto endOfWorld;
185     }
186
187   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
188   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
189
190   /* if no usage of r0 then return it */
191   if (!r0iu && !r0ou)
192     {
193       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
194       (*aopp)->type = AOP_R0;
195
196       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
197     }
198
199   /* if no usage of r1 then return it */
200   if (!r1iu && !r1ou)
201     {
202       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
203       (*aopp)->type = AOP_R1;
204
205       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
206     }
207
208   /* now we know they both have usage */
209   /* if r0 not used in this instruction */
210   if (!r0iu)
211     {
212       /* push it if not already pushed */
213       if (!_G.r0Pushed)
214         {
215           emitcode ("push", "%s",
216                     ds390_regWithIdx (R0_IDX)->dname);
217           _G.r0Pushed++;
218         }
219
220       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
221       (*aopp)->type = AOP_R0;
222
223       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
224     }
225
226   /* if r1 not used then */
227
228   if (!r1iu)
229     {
230       /* push it if not already pushed */
231       if (!_G.r1Pushed)
232         {
233           emitcode ("push", "%s",
234                     ds390_regWithIdx (R1_IDX)->dname);
235           _G.r1Pushed++;
236         }
237
238       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
239       (*aopp)->type = AOP_R1;
240       return ds390_regWithIdx (R1_IDX);
241     }
242
243 endOfWorld:
244   /* I said end of world but not quite end of world yet */
245   /* if this is a result then we can push it on the stack */
246   if (result)
247     {
248       (*aopp)->type = AOP_STK;
249       return NULL;
250     }
251
252   /* other wise this is true end of the world */
253   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
254           "getFreePtr should never reach here");
255   exit (1);
256 }
257
258 /*-----------------------------------------------------------------*/
259 /* newAsmop - creates a new asmOp                                  */
260 /*-----------------------------------------------------------------*/
261 static asmop *
262 newAsmop (short type)
263 {
264   asmop *aop;
265
266   aop = Safe_calloc (1, sizeof (asmop));
267   aop->type = type;
268   return aop;
269 }
270
271 static int _currentDPS;         /* Current processor DPS. */
272 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
273 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
274
275 /*-----------------------------------------------------------------*/
276 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
277 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
278 /* alternate DPTR (DPL1/DPH1/DPX1).          */
279 /*-----------------------------------------------------------------*/
280 static void
281 genSetDPTR (int n)
282 {
283
284   /* If we are doing lazy evaluation, simply note the desired
285    * change, but don't emit any code yet.
286    */
287   if (_lazyDPS)
288     {
289       _desiredDPS = n;
290       return;
291     }
292
293   if (!n)
294     {
295       emitcode ("mov", "dps, #0x00");
296     }
297   else
298     {
299       TR_DPTR("#1");
300       emitcode ("mov", "dps, #0x01");
301     }
302 }
303
304 /*-----------------------------------------------------------------*/
305 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
306 /*                   */
307 /* Any code that operates on DPTR (NB: not on the individual     */
308 /* components, like DPH) *must* call _flushLazyDPS() before using  */
309 /* DPTR within a lazy DPS evaluation block.        */
310 /*                   */
311 /* Note that aopPut and aopGet already contain the proper calls to */
312 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
313 /* DPS evaluation block.             */
314 /*                   */
315 /* Also, _flushLazyDPS must be called before any flow control      */
316 /* operations that could potentially branch out of the block.    */
317 /*                         */
318 /* Lazy DPS evaluation is simply an optimization (though an      */
319 /* important one), so if in doubt, leave it out.       */
320 /*-----------------------------------------------------------------*/
321 static void
322 _startLazyDPSEvaluation (void)
323 {
324   _currentDPS = 0;
325   _desiredDPS = 0;
326 #ifdef BETTER_LITERAL_SHIFT  
327   _lazyDPS++;
328 #else
329   _lazyDPS = 1;
330 #endif  
331 }
332
333 /*-----------------------------------------------------------------*/
334 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
335 /* desired one. Call before using DPTR within a lazy DPS evaluation */
336 /* block.                */
337 /*-----------------------------------------------------------------*/
338 static void
339 _flushLazyDPS (void)
340 {
341   if (!_lazyDPS)
342     {
343       /* nothing to do. */
344       return;
345     }
346
347   if (_desiredDPS != _currentDPS)
348     {
349       if (_desiredDPS)
350         {
351           emitcode ("inc", "dps");
352         }
353       else
354         {
355           emitcode ("dec", "dps");
356         }
357       _currentDPS = _desiredDPS;
358     }
359 }
360
361 /*-----------------------------------------------------------------*/
362 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
363 /*                   */
364 /* Forces us back to the safe state (standard DPTR selected).    */
365 /*-----------------------------------------------------------------*/
366 static void
367 _endLazyDPSEvaluation (void)
368 {
369 #ifdef BETTER_LITERAL_SHIFT  
370   _lazyDPS--;
371 #else
372   _lazyDPS = 0;
373 #endif    
374   if (!_lazyDPS)
375   {
376     if (_currentDPS)
377     {
378       genSetDPTR (0);
379       _flushLazyDPS ();
380     }
381     _currentDPS = 0;
382     _desiredDPS = 0;
383   }
384 }
385
386
387
388 /*-----------------------------------------------------------------*/
389 /* pointerCode - returns the code for a pointer type               */
390 /*-----------------------------------------------------------------*/
391 static int
392 pointerCode (sym_link * etype)
393 {
394
395   return PTR_TYPE (SPEC_OCLS (etype));
396
397 }
398
399 /*-----------------------------------------------------------------*/
400 /* aopForSym - for a true symbol                                   */
401 /*-----------------------------------------------------------------*/
402 static asmop *
403 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
404 {
405   asmop *aop;
406   memmap *space = SPEC_OCLS (sym->etype);
407
408   /* if already has one */
409   if (sym->aop)
410     return sym->aop;
411
412   /* assign depending on the storage class */
413   /* if it is on the stack or indirectly addressable */
414   /* space we need to assign either r0 or r1 to it   */
415   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
416     {
417       sym->aop = aop = newAsmop (0);
418       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
419       aop->size = getSize (sym->type);
420
421       /* now assign the address of the variable to
422          the pointer register */
423       if (aop->type != AOP_STK)
424         {
425
426           if (sym->onStack)
427             {
428               if (_G.accInUse)
429                 emitcode ("push", "acc");
430
431               emitcode ("mov", "a,_bp");
432               emitcode ("add", "a,#0x%02x",
433                         ((sym->stack < 0) ?
434                          ((char) (sym->stack - _G.nRegsSaved)) :
435                          ((char) sym->stack)) & 0xff);
436               emitcode ("mov", "%s,a",
437                         aop->aopu.aop_ptr->name);
438
439               if (_G.accInUse)
440                 emitcode ("pop", "acc");
441             }
442           else
443             emitcode ("mov", "%s,#%s",
444                       aop->aopu.aop_ptr->name,
445                       sym->rname);
446           aop->paged = space->paged;
447         }
448       else
449         aop->aopu.aop_stk = sym->stack;
450       return aop;
451     }
452
453   if (sym->onStack && options.stack10bit)
454     {
455       /* It's on the 10 bit stack, which is located in
456        * far data space.
457        */
458
459       if (_G.accInUse)
460         emitcode ("push", "acc");
461
462       emitcode ("mov", "a,_bp");
463       emitcode ("add", "a,#0x%02x",
464                 ((sym->stack < 0) ?
465                  ((char) (sym->stack - _G.nRegsSaved)) :
466                  ((char) sym->stack)) & 0xff);
467
468       if (useDP2)
469         {
470           if (options.model == MODEL_FLAT24)
471             emitcode ("mov", "dpx1,#0x40");
472    TR_DPTR("#2");
473           emitcode ("mov", "dph1,#0x00");
474           emitcode ("mov", "dpl1, a");
475         }
476       else
477         {
478           if (options.model == MODEL_FLAT24)
479             emitcode ("mov", "dpx,#0x40");
480           emitcode ("mov", "dph,#0x00");
481           emitcode ("mov", "dpl, a");
482         }
483
484       if (_G.accInUse)
485         emitcode ("pop", "acc");
486
487       sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
488       aop->size = getSize (sym->type);
489       return aop;
490     }
491
492   /* if in bit space */
493   if (IN_BITSPACE (space))
494     {
495       sym->aop = aop = newAsmop (AOP_CRY);
496       aop->aopu.aop_dir = sym->rname;
497       aop->size = getSize (sym->type);
498       return aop;
499     }
500   /* if it is in direct space */
501   if (IN_DIRSPACE (space))
502     {
503       sym->aop = aop = newAsmop (AOP_DIR);
504       aop->aopu.aop_dir = sym->rname;
505       aop->size = getSize (sym->type);
506       return aop;
507     }
508
509   /* special case for a function */
510   if (IS_FUNC (sym->type))
511     {
512       sym->aop = aop = newAsmop (AOP_IMMD);
513       aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
514       strcpy (aop->aopu.aop_immd, sym->rname);
515       aop->size = FPTRSIZE;
516       return aop;
517     }
518
519   /* only remaining is far space */
520   /* in which case DPTR gets the address */
521   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
522   if (useDP2)
523     {
524       genSetDPTR (1);
525       _flushLazyDPS ();
526       emitcode ("mov", "dptr,#%s", sym->rname);
527       genSetDPTR (0);
528     }
529   else
530     {
531       emitcode ("mov", "dptr,#%s", sym->rname);
532     }
533   aop->size = getSize (sym->type);
534
535   /* if it is in code space */
536   if (IN_CODESPACE (space))
537     aop->code = 1;
538
539   return aop;
540 }
541
542 /*-----------------------------------------------------------------*/
543 /* aopForRemat - rematerialzes an object                           */
544 /*-----------------------------------------------------------------*/
545 static asmop *
546 aopForRemat (symbol * sym)
547 {
548   iCode *ic = sym->rematiCode;
549   asmop *aop = newAsmop (AOP_IMMD);
550
551   int val = 0;
552
553   for (;;)
554     {
555       if (ic->op == '+')
556         val += (int) operandLitValue (IC_RIGHT (ic));
557       else if (ic->op == '-')
558         val -= (int) operandLitValue (IC_RIGHT (ic));
559       else
560         break;
561
562       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
563     }
564
565   if (val)
566     sprintf (buffer, "(%s %c 0x%04x)",
567              OP_SYMBOL (IC_LEFT (ic))->rname,
568              val >= 0 ? '+' : '-',
569              abs (val) & 0xffff);
570   else
571     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
572
573   aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
574   strcpy (aop->aopu.aop_immd, buffer);
575   return aop;
576 }
577
578 /*-----------------------------------------------------------------*/
579 /* regsInCommon - two operands have some registers in common       */
580 /*-----------------------------------------------------------------*/
581 static bool
582 regsInCommon (operand * op1, operand * op2)
583 {
584   symbol *sym1, *sym2;
585   int i;
586
587   /* if they have registers in common */
588   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
589     return FALSE;
590
591   sym1 = OP_SYMBOL (op1);
592   sym2 = OP_SYMBOL (op2);
593
594   if (sym1->nRegs == 0 || sym2->nRegs == 0)
595     return FALSE;
596
597   for (i = 0; i < sym1->nRegs; i++)
598     {
599       int j;
600       if (!sym1->regs[i])
601         continue;
602
603       for (j = 0; j < sym2->nRegs; j++)
604         {
605           if (!sym2->regs[j])
606             continue;
607
608           if (sym2->regs[j] == sym1->regs[i])
609             return TRUE;
610         }
611     }
612
613   return FALSE;
614 }
615
616 /*-----------------------------------------------------------------*/
617 /* operandsEqu - equivalent                                        */
618 /*-----------------------------------------------------------------*/
619 static bool
620 operandsEqu (operand * op1, operand * op2)
621 {
622   symbol *sym1, *sym2;
623
624   /* if they not symbols */
625   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
626     return FALSE;
627
628   sym1 = OP_SYMBOL (op1);
629   sym2 = OP_SYMBOL (op2);
630
631   /* if both are itemps & one is spilt
632      and the other is not then false */
633   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
634       sym1->isspilt != sym2->isspilt)
635     return FALSE;
636
637   /* if they are the same */
638   if (sym1 == sym2)
639     return TRUE;
640
641   if (strcmp (sym1->rname, sym2->rname) == 0)
642     return TRUE;
643
644
645   /* if left is a tmp & right is not */
646   if (IS_ITEMP (op1) &&
647       !IS_ITEMP (op2) &&
648       sym1->isspilt &&
649       (sym1->usl.spillLoc == sym2))
650     return TRUE;
651
652   if (IS_ITEMP (op2) &&
653       !IS_ITEMP (op1) &&
654       sym2->isspilt &&
655       sym1->level > 0 &&
656       (sym2->usl.spillLoc == sym1))
657     return TRUE;
658
659   return FALSE;
660 }
661
662 /*-----------------------------------------------------------------*/
663 /* sameRegs - two asmops have the same registers                   */
664 /*-----------------------------------------------------------------*/
665 static bool
666 sameRegs (asmop * aop1, asmop * aop2)
667 {
668   int i;
669
670   if (aop1 == aop2)
671     {
672       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
673         {
674           return FALSE;
675         }
676       return TRUE;
677     }
678
679   if (aop1->type != AOP_REG ||
680       aop2->type != AOP_REG)
681     return FALSE;
682
683   if (aop1->size != aop2->size)
684     return FALSE;
685
686   for (i = 0; i < aop1->size; i++)
687     if (aop1->aopu.aop_reg[i] !=
688         aop2->aopu.aop_reg[i])
689       return FALSE;
690
691   return TRUE;
692 }
693
694 /*-----------------------------------------------------------------*/
695 /* aopOp - allocates an asmop for an operand  :                    */
696 /*-----------------------------------------------------------------*/
697 static void
698 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
699 {
700   asmop *aop;
701   symbol *sym;
702   int i;
703
704   if (!op)
705     return;
706
707   /* if this a literal */
708   if (IS_OP_LITERAL (op))
709     {
710       op->aop = aop = newAsmop (AOP_LIT);
711       aop->aopu.aop_lit = op->operand.valOperand;
712       aop->size = getSize (operandType (op));
713       return;
714     }
715
716   /* if already has a asmop then continue */
717   if (op->aop)
718     return;
719
720   /* if the underlying symbol has a aop */
721   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
722     {
723       op->aop = OP_SYMBOL (op)->aop;
724       return;
725     }
726
727   /* if this is a true symbol */
728   if (IS_TRUE_SYMOP (op))
729     {
730       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
731       return;
732     }
733
734   /* this is a temporary : this has
735      only four choices :
736      a) register
737      b) spillocation
738      c) rematerialize
739      d) conditional
740      e) can be a return use only */
741
742   sym = OP_SYMBOL (op);
743
744
745   /* if the type is a conditional */
746   if (sym->regType == REG_CND)
747     {
748       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
749       aop->size = 0;
750       return;
751     }
752
753   /* if it is spilt then two situations
754      a) is rematerialize
755      b) has a spill location */
756   if (sym->isspilt || sym->nRegs == 0)
757     {
758
759       /* rematerialize it NOW */
760       if (sym->remat)
761         {
762           sym->aop = op->aop = aop =
763             aopForRemat (sym);
764           aop->size = getSize (sym->type);
765           return;
766         }
767
768       if (sym->accuse)
769         {
770           int i;
771           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
772           aop->size = getSize (sym->type);
773           for (i = 0; i < 2; i++)
774             aop->aopu.aop_str[i] = accUse[i];
775           return;
776         }
777
778       if (sym->ruonly)
779         {
780           int i;
781
782           if (useDP2)
783             {
784               /* a AOP_STR uses DPTR, but DPTR is already in use;
785                * we're just hosed.
786                */
787               fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
788             }
789
790           aop = op->aop = sym->aop = newAsmop (AOP_STR);
791           aop->size = getSize (sym->type);
792           for (i = 0; i < (int) fReturnSizeDS390; i++)
793             aop->aopu.aop_str[i] = fReturn[i];
794           return;
795         }
796
797       /* else spill location  */
798       sym->aop = op->aop = aop =
799         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
800       aop->size = getSize (sym->type);
801       return;
802     }
803
804   /* must be in a register */
805   sym->aop = op->aop = aop = newAsmop (AOP_REG);
806   aop->size = sym->nRegs;
807   for (i = 0; i < sym->nRegs; i++)
808     aop->aopu.aop_reg[i] = sym->regs[i];
809 }
810
811 /*-----------------------------------------------------------------*/
812 /* freeAsmop - free up the asmop given to an operand               */
813 /*----------------------------------------------------------------*/
814 static void
815 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
816 {
817   asmop *aop;
818
819   if (!op)
820     aop = aaop;
821   else
822     aop = op->aop;
823
824   if (!aop)
825     return;
826
827   if (aop->freed)
828     goto dealloc;
829
830   aop->freed = 1;
831
832   /* depending on the asmop type only three cases need work AOP_RO
833      , AOP_R1 && AOP_STK */
834   switch (aop->type)
835     {
836     case AOP_R0:
837       if (_G.r0Pushed)
838         {
839           if (pop)
840             {
841               emitcode ("pop", "ar0");
842               _G.r0Pushed--;
843             }
844         }
845       bitVectUnSetBit (ic->rUsed, R0_IDX);
846       break;
847
848     case AOP_R1:
849       if (_G.r1Pushed)
850         {
851           if (pop)
852             {
853               emitcode ("pop", "ar1");
854               _G.r1Pushed--;
855             }
856         }
857       bitVectUnSetBit (ic->rUsed, R1_IDX);
858       break;
859
860     case AOP_STK:
861       {
862         int sz = aop->size;
863         int stk = aop->aopu.aop_stk + aop->size;
864         bitVectUnSetBit (ic->rUsed, R0_IDX);
865         bitVectUnSetBit (ic->rUsed, R1_IDX);
866
867         getFreePtr (ic, &aop, FALSE);
868
869         if (options.stack10bit)
870           {
871             /* I'm not sure what to do here yet... */
872             /* #STUB */
873             fprintf (stderr,
874                      "*** Warning: probably generating bad code for "
875                      "10 bit stack mode.\n");
876           }
877
878         if (stk)
879           {
880             emitcode ("mov", "a,_bp");
881             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
882             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
883           }
884         else
885           {
886             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
887           }
888
889         while (sz--)
890           {
891             emitcode ("pop", "acc");
892             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
893             if (!sz)
894               break;
895             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
896           }
897         op->aop = aop;
898         freeAsmop (op, NULL, ic, TRUE);
899         if (_G.r0Pushed)
900           {
901             emitcode ("pop", "ar0");
902             _G.r0Pushed--;
903           }
904
905         if (_G.r1Pushed)
906           {
907             emitcode ("pop", "ar1");
908             _G.r1Pushed--;
909           }
910       }
911     }
912
913 dealloc:
914   /* all other cases just dealloc */
915   if (op)
916     {
917       op->aop = NULL;
918       if (IS_SYMOP (op))
919         {
920           OP_SYMBOL (op)->aop = NULL;
921           /* if the symbol has a spill */
922           if (SPIL_LOC (op))
923             SPIL_LOC (op)->aop = NULL;
924         }
925     }
926 }
927
928 /*------------------------------------------------------------------*/
929 /* aopGet - for fetching value of the aop                           */
930 /*                    */
931 /* Set canClobberACC if you are sure it is OK to clobber the value  */
932 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
933 /* just less efficient.               */
934 /*------------------------------------------------------------------*/
935
936 static char *
937 aopGet (asmop * aop,
938         int offset,
939         bool bit16,
940         bool dname,
941         bool canClobberACC)
942 {
943   char *s = buffer;
944   char *rs;
945
946   /* offset is greater than
947      size then zero */
948   if (offset > (aop->size - 1) &&
949       aop->type != AOP_LIT)
950     return zero;
951
952   /* depending on type */
953   switch (aop->type)
954     {
955
956     case AOP_R0:
957     case AOP_R1:
958       /* if we need to increment it */
959       while (offset > aop->coff)
960         {
961           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
962           aop->coff++;
963         }
964
965       while (offset < aop->coff)
966         {
967           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
968           aop->coff--;
969         }
970
971       aop->coff = offset;
972       if (aop->paged)
973         {
974           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
975           return (dname ? "acc" : "a");
976         }
977       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
978       rs = Safe_calloc (1, strlen (s) + 1);
979       strcpy (rs, s);
980       return rs;
981
982     case AOP_DPTR:
983     case AOP_DPTR2:
984
985       if (aop->type == AOP_DPTR2)
986         {
987           genSetDPTR (1);
988           if (!canClobberACC)
989             {
990        TR_AP("#1");
991               emitcode ("xch", "a, %s", DP2_RESULT_REG);
992             }
993         }
994
995       _flushLazyDPS ();
996
997       while (offset > aop->coff)
998         {
999           emitcode ("inc", "dptr");
1000           aop->coff++;
1001         }
1002
1003       while (offset < aop->coff)
1004         {
1005           emitcode ("lcall", "__decdptr");
1006           aop->coff--;
1007         }
1008
1009       aop->coff = offset;
1010       if (aop->code)
1011         {
1012           emitcode ("clr", "a");
1013           emitcode ("movc", "a,@a+dptr");
1014         }
1015       else
1016         {
1017           emitcode ("movx", "a,@dptr");
1018         }
1019
1020       if (aop->type == AOP_DPTR2)
1021         {
1022           genSetDPTR (0);
1023           if (!canClobberACC)
1024             {
1025        TR_AP("#2");
1026               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1027               return DP2_RESULT_REG;
1028             }
1029         }
1030       return (dname ? "acc" : "a");
1031
1032     case AOP_IMMD:
1033       if (bit16)
1034         sprintf (s, "#%s", aop->aopu.aop_immd);
1035       else if (offset)
1036         sprintf (s, "#(%s >> %d)",
1037                  aop->aopu.aop_immd,
1038                  offset * 8);
1039       else
1040         sprintf (s, "#%s",
1041                  aop->aopu.aop_immd);
1042       rs = Safe_calloc (1, strlen (s) + 1);
1043       strcpy (rs, s);
1044       return rs;
1045
1046     case AOP_DIR:
1047       if (offset)
1048         sprintf (s, "(%s + %d)",
1049                  aop->aopu.aop_dir,
1050                  offset);
1051       else
1052         sprintf (s, "%s", aop->aopu.aop_dir);
1053       rs = Safe_calloc (1, strlen (s) + 1);
1054       strcpy (rs, s);
1055       return rs;
1056
1057     case AOP_REG:
1058       if (dname)
1059         return aop->aopu.aop_reg[offset]->dname;
1060       else
1061         return aop->aopu.aop_reg[offset]->name;
1062
1063     case AOP_CRY:
1064       emitcode ("clr", "a");
1065       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1066       emitcode ("rlc", "a");
1067       return (dname ? "acc" : "a");
1068
1069     case AOP_ACC:
1070       if (!offset && dname)
1071         return "acc";
1072       return aop->aopu.aop_str[offset];
1073
1074     case AOP_LIT:
1075       return aopLiteral (aop->aopu.aop_lit, offset);
1076
1077     case AOP_STR:
1078       aop->coff = offset;
1079       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1080           dname)
1081         return "acc";
1082
1083       return aop->aopu.aop_str[offset];
1084
1085     }
1086
1087   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1088           "aopget got unsupported aop->type");
1089   exit (1);
1090 }
1091 /*-----------------------------------------------------------------*/
1092 /* aopPut - puts a string for a aop                                */
1093 /*-----------------------------------------------------------------*/
1094 static void
1095 aopPut (asmop * aop, char *s, int offset)
1096 {
1097   char *d = buffer;
1098
1099   if (aop->size && offset > (aop->size - 1))
1100     {
1101       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1102               "aopPut got offset > aop->size");
1103       exit (1);
1104     }
1105
1106   /* will assign value to value */
1107   /* depending on where it is ofcourse */
1108   switch (aop->type)
1109     {
1110     case AOP_DIR:
1111       if (offset)
1112         sprintf (d, "(%s + %d)",
1113                  aop->aopu.aop_dir, offset);
1114       else
1115         sprintf (d, "%s", aop->aopu.aop_dir);
1116
1117       if (strcmp (d, s))
1118         emitcode ("mov", "%s,%s", d, s);
1119
1120       break;
1121
1122     case AOP_REG:
1123       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1124           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1125         {
1126           if (*s == '@' ||
1127               strcmp (s, "r0") == 0 ||
1128               strcmp (s, "r1") == 0 ||
1129               strcmp (s, "r2") == 0 ||
1130               strcmp (s, "r3") == 0 ||
1131               strcmp (s, "r4") == 0 ||
1132               strcmp (s, "r5") == 0 ||
1133               strcmp (s, "r6") == 0 ||
1134               strcmp (s, "r7") == 0)
1135             emitcode ("mov", "%s,%s",
1136                       aop->aopu.aop_reg[offset]->dname, s);
1137           else
1138             emitcode ("mov", "%s,%s",
1139                       aop->aopu.aop_reg[offset]->name, s);
1140         }
1141       break;
1142
1143     case AOP_DPTR:
1144     case AOP_DPTR2:
1145
1146       if (aop->type == AOP_DPTR2)
1147         {
1148           genSetDPTR (1);
1149         }
1150       _flushLazyDPS ();
1151
1152       if (aop->code)
1153         {
1154           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1155                   "aopPut writting to code space");
1156           exit (1);
1157         }
1158
1159       while (offset > aop->coff)
1160         {
1161           aop->coff++;
1162           emitcode ("inc", "dptr");
1163         }
1164
1165       while (offset < aop->coff)
1166         {
1167           aop->coff--;
1168           emitcode ("lcall", "__decdptr");
1169         }
1170
1171       aop->coff = offset;
1172
1173       /* if not in accumulater */
1174       MOVA (s);
1175
1176       emitcode ("movx", "@dptr,a");
1177
1178       if (aop->type == AOP_DPTR2)
1179         {
1180           genSetDPTR (0);
1181         }
1182       break;
1183
1184     case AOP_R0:
1185     case AOP_R1:
1186       while (offset > aop->coff)
1187         {
1188           aop->coff++;
1189           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1190         }
1191       while (offset < aop->coff)
1192         {
1193           aop->coff--;
1194           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1195         }
1196       aop->coff = offset;
1197
1198       if (aop->paged)
1199         {
1200           MOVA (s);
1201           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1202
1203         }
1204       else if (*s == '@')
1205         {
1206           MOVA (s);
1207           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1208         }
1209       else if (strcmp (s, "r0") == 0 ||
1210                strcmp (s, "r1") == 0 ||
1211                strcmp (s, "r2") == 0 ||
1212                strcmp (s, "r3") == 0 ||
1213                strcmp (s, "r4") == 0 ||
1214                strcmp (s, "r5") == 0 ||
1215                strcmp (s, "r6") == 0 ||
1216                strcmp (s, "r7") == 0)
1217         {
1218           char buffer[10];
1219           sprintf (buffer, "a%s", s);
1220           emitcode ("mov", "@%s,%s",
1221                     aop->aopu.aop_ptr->name, buffer);
1222         }
1223       else
1224         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1225
1226       break;
1227
1228     case AOP_STK:
1229       if (strcmp (s, "a") == 0)
1230         emitcode ("push", "acc");
1231       else
1232         emitcode ("push", "%s", s);
1233
1234       break;
1235
1236     case AOP_CRY:
1237       /* if bit variable */
1238       if (!aop->aopu.aop_dir)
1239         {
1240           emitcode ("clr", "a");
1241           emitcode ("rlc", "a");
1242         }
1243       else
1244         {
1245           if (s == zero)
1246             emitcode ("clr", "%s", aop->aopu.aop_dir);
1247           else if (s == one)
1248             emitcode ("setb", "%s", aop->aopu.aop_dir);
1249           else if (!strcmp (s, "c"))
1250             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1251           else
1252             {
1253               if (strcmp (s, "a"))
1254                 {
1255                   MOVA (s);
1256                 }
1257               {
1258                 symbol *lbl = newiTempLabel (NULL);
1259                 emitcode ("clr", "c");
1260                 emitcode ("jz", "%05d$", lbl->key + 100);
1261                 emitcode ("cpl", "c");
1262                 emitcode ("", "%05d$:", lbl->key + 100);
1263                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1264               }
1265             }
1266         }
1267       break;
1268
1269     case AOP_STR:
1270       aop->coff = offset;
1271       if (strcmp (aop->aopu.aop_str[offset], s))
1272         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1273       break;
1274
1275     case AOP_ACC:
1276       aop->coff = offset;
1277       if (!offset && (strcmp (s, "acc") == 0))
1278         break;
1279
1280       if (strcmp (aop->aopu.aop_str[offset], s))
1281         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1282       break;
1283
1284     default:
1285       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1286               "aopPut got unsupported aop->type");
1287       exit (1);
1288     }
1289
1290 }
1291
1292
1293 /*--------------------------------------------------------------------*/
1294 /* reAdjustPreg - points a register back to where it should (coff==0) */
1295 /*--------------------------------------------------------------------*/
1296 static void
1297 reAdjustPreg (asmop * aop)
1298 {
1299   if ((aop->coff==0) || (aop->size <= 1)) {
1300     return;
1301   }
1302
1303   switch (aop->type)
1304     {
1305     case AOP_R0:
1306     case AOP_R1:
1307       while (aop->coff--)
1308         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1309       break;
1310     case AOP_DPTR:
1311     case AOP_DPTR2:
1312       if (aop->type == AOP_DPTR2)
1313         {
1314           genSetDPTR (1);
1315           _flushLazyDPS ();
1316         }
1317       while (aop->coff--)
1318         {
1319           emitcode ("lcall", "__decdptr");
1320         }
1321
1322       if (aop->type == AOP_DPTR2)
1323         {
1324           genSetDPTR (0);
1325         }
1326       break;
1327
1328     }
1329   aop->coff=0;
1330 }
1331
1332 #define AOP(op) op->aop
1333 #define AOP_TYPE(op) AOP(op)->type
1334 #define AOP_SIZE(op) AOP(op)->size
1335 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1336                        AOP_TYPE(x) == AOP_R0))
1337
1338 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1339                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1340                          AOP(x)->paged))
1341
1342 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1343                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1344                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1345
1346 /* Workaround for DS80C390 bug: div ab may return bogus results
1347  * if A is accessed in instruction immediately before the div.
1348  *
1349  * Will be fixed in B4 rev of processor, Dallas claims.
1350  */
1351
1352 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1353     if (!AOP_NEEDSACC(RIGHT))         \
1354     {               \
1355       /* We can load A first, then B, since     \
1356        * B (the RIGHT operand) won't clobber A,   \
1357        * thus avoiding touching A right before the div. \
1358        */             \
1359       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1360       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1361       MOVA(L);            \
1362       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1363     }               \
1364     else              \
1365     {               \
1366       /* Just stuff in a nop after loading A. */    \
1367       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1368       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1369       MOVA(L);            \
1370       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1371     }
1372
1373 /*-----------------------------------------------------------------*/
1374 /* genNotFloat - generates not for float operations              */
1375 /*-----------------------------------------------------------------*/
1376 static void
1377 genNotFloat (operand * op, operand * res)
1378 {
1379   int size, offset;
1380   char *l;
1381   symbol *tlbl;
1382
1383   D (emitcode (";", "genNotFloat ");
1384     );
1385
1386   /* we will put 127 in the first byte of
1387      the result */
1388   aopPut (AOP (res), "#127", 0);
1389   size = AOP_SIZE (op) - 1;
1390   offset = 1;
1391
1392   _startLazyDPSEvaluation ();
1393   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1394   MOVA (l);
1395
1396   while (size--)
1397     {
1398       emitcode ("orl", "a,%s",
1399                 aopGet (op->aop,
1400                         offset++, FALSE, FALSE, FALSE));
1401     }
1402   _endLazyDPSEvaluation ();
1403
1404   tlbl = newiTempLabel (NULL);
1405   aopPut (res->aop, one, 1);
1406   emitcode ("jz", "%05d$", (tlbl->key + 100));
1407   aopPut (res->aop, zero, 1);
1408   emitcode ("", "%05d$:", (tlbl->key + 100));
1409
1410   size = res->aop->size - 2;
1411   offset = 2;
1412   /* put zeros in the rest */
1413   while (size--)
1414     aopPut (res->aop, zero, offset++);
1415 }
1416
1417 /*-----------------------------------------------------------------*/
1418 /* opIsGptr: returns non-zero if the passed operand is       */
1419 /* a generic pointer type.             */
1420 /*-----------------------------------------------------------------*/
1421 static int
1422 opIsGptr (operand * op)
1423 {
1424   sym_link *type = operandType (op);
1425
1426   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1427     {
1428       return 1;
1429     }
1430   return 0;
1431 }
1432
1433 /*-----------------------------------------------------------------*/
1434 /* getDataSize - get the operand data size                         */
1435 /*-----------------------------------------------------------------*/
1436 static int
1437 getDataSize (operand * op)
1438 {
1439   int size;
1440   size = AOP_SIZE (op);
1441   if (size == GPTRSIZE)
1442     {
1443       sym_link *type = operandType (op);
1444       if (IS_GENPTR (type))
1445         {
1446           /* generic pointer; arithmetic operations
1447            * should ignore the high byte (pointer type).
1448            */
1449           size--;
1450         }
1451     }
1452   return size;
1453 }
1454
1455 /*-----------------------------------------------------------------*/
1456 /* outAcc - output Acc                                             */
1457 /*-----------------------------------------------------------------*/
1458 static void
1459 outAcc (operand * result)
1460 {
1461   int size, offset;
1462   size = getDataSize (result);
1463   if (size)
1464     {
1465       aopPut (AOP (result), "a", 0);
1466       size--;
1467       offset = 1;
1468       /* unsigned or positive */
1469       while (size--)
1470         {
1471           aopPut (AOP (result), zero, offset++);
1472         }
1473     }
1474 }
1475
1476 /*-----------------------------------------------------------------*/
1477 /* outBitC - output a bit C                                        */
1478 /*-----------------------------------------------------------------*/
1479 static void
1480 outBitC (operand * result)
1481 {
1482   /* if the result is bit */
1483   if (AOP_TYPE (result) == AOP_CRY)
1484     {
1485       aopPut (AOP (result), "c", 0);
1486     }
1487   else
1488     {
1489       emitcode ("clr", "a");
1490       emitcode ("rlc", "a");
1491       outAcc (result);
1492     }
1493 }
1494
1495 /*-----------------------------------------------------------------*/
1496 /* toBoolean - emit code for orl a,operator(sizeop)                */
1497 /*-----------------------------------------------------------------*/
1498 static void
1499 toBoolean (operand * oper)
1500 {
1501   int   size = AOP_SIZE (oper) - 1;
1502   int   offset = 1;
1503   bool usedB = FALSE;
1504
1505   /* The generic part of a generic pointer should
1506    * not participate in it's truth value.
1507    *
1508    * i.e. 0x10000000 is zero.
1509    */
1510   if (opIsGptr (oper))
1511     {
1512       D (emitcode (";", "toBoolean: generic ptr special case.");
1513         );
1514       size--;
1515     }
1516
1517   _startLazyDPSEvaluation ();
1518   if (AOP_NEEDSACC (oper) && size)
1519     {
1520       usedB = TRUE;
1521       emitcode ("push", "b");
1522       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1523     }
1524   else
1525     {
1526       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1527     }
1528   while (size--)
1529     {
1530       if (usedB)
1531         {
1532           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1533         }
1534       else
1535         {
1536           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1537         }
1538     }
1539   _endLazyDPSEvaluation ();
1540
1541   if (usedB)
1542     {
1543       emitcode ("mov", "a,b");
1544       emitcode ("pop", "b");
1545     }
1546 }
1547
1548
1549 /*-----------------------------------------------------------------*/
1550 /* genNot - generate code for ! operation                          */
1551 /*-----------------------------------------------------------------*/
1552 static void
1553 genNot (iCode * ic)
1554 {
1555   symbol *tlbl;
1556   sym_link *optype = operandType (IC_LEFT (ic));
1557
1558   D (emitcode (";", "genNot ");
1559     );
1560
1561   /* assign asmOps to operand & result */
1562   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1563   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1564
1565   /* if in bit space then a special case */
1566   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1567     {
1568       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1569       emitcode ("cpl", "c");
1570       outBitC (IC_RESULT (ic));
1571       goto release;
1572     }
1573
1574   /* if type float then do float */
1575   if (IS_FLOAT (optype))
1576     {
1577       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1578       goto release;
1579     }
1580
1581   toBoolean (IC_LEFT (ic));
1582
1583   tlbl = newiTempLabel (NULL);
1584   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1585   emitcode ("", "%05d$:", tlbl->key + 100);
1586   outBitC (IC_RESULT (ic));
1587
1588 release:
1589   /* release the aops */
1590   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1591   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1592 }
1593
1594
1595 /*-----------------------------------------------------------------*/
1596 /* genCpl - generate code for complement                           */
1597 /*-----------------------------------------------------------------*/
1598 static void
1599 genCpl (iCode * ic)
1600 {
1601   int offset = 0;
1602   int size;
1603
1604   D (emitcode (";", "genCpl ");
1605     );
1606
1607
1608   /* assign asmOps to operand & result */
1609   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1610   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1611
1612   /* if both are in bit space then
1613      a special case */
1614   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1615       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1616     {
1617
1618       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1619       emitcode ("cpl", "c");
1620       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1621       goto release;
1622     }
1623
1624   size = AOP_SIZE (IC_RESULT (ic));
1625   _startLazyDPSEvaluation ();
1626   while (size--)
1627     {
1628       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1629       MOVA (l);
1630       emitcode ("cpl", "a");
1631       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1632     }
1633   _endLazyDPSEvaluation ();
1634
1635
1636 release:
1637   /* release the aops */
1638   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1639   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1640 }
1641
1642 /*-----------------------------------------------------------------*/
1643 /* genUminusFloat - unary minus for floating points                */
1644 /*-----------------------------------------------------------------*/
1645 static void
1646 genUminusFloat (operand * op, operand * result)
1647 {
1648   int size, offset = 0;
1649   char *l;
1650   /* for this we just need to flip the
1651      first it then copy the rest in place */
1652   D (emitcode (";", "genUminusFloat");
1653     );
1654
1655   _startLazyDPSEvaluation ();
1656   size = AOP_SIZE (op) - 1;
1657   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1658   MOVA (l);
1659
1660   emitcode ("cpl", "acc.7");
1661   aopPut (AOP (result), "a", 3);
1662
1663   while (size--)
1664     {
1665       aopPut (AOP (result),
1666               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1667               offset);
1668       offset++;
1669     }
1670   _endLazyDPSEvaluation ();
1671 }
1672
1673 /*-----------------------------------------------------------------*/
1674 /* genUminus - unary minus code generation                         */
1675 /*-----------------------------------------------------------------*/
1676 static void
1677 genUminus (iCode * ic)
1678 {
1679   int offset, size;
1680   sym_link *optype, *rtype;
1681
1682   D (emitcode (";", "genUminus ");
1683     );
1684
1685
1686   /* assign asmops */
1687   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1688   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1689
1690   /* if both in bit space then special
1691      case */
1692   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1693       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1694     {
1695
1696       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1697       emitcode ("cpl", "c");
1698       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1699       goto release;
1700     }
1701
1702   optype = operandType (IC_LEFT (ic));
1703   rtype = operandType (IC_RESULT (ic));
1704
1705   /* if float then do float stuff */
1706   if (IS_FLOAT (optype))
1707     {
1708       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1709       goto release;
1710     }
1711
1712   /* otherwise subtract from zero */
1713   size = AOP_SIZE (IC_LEFT (ic));
1714   offset = 0;
1715   _startLazyDPSEvaluation ();
1716   while (size--)
1717     {
1718       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1719       if (!strcmp (l, "a"))
1720         {
1721           if (offset == 0)
1722             SETC;
1723           emitcode ("cpl", "a");
1724           emitcode ("addc", "a,#0");
1725         }
1726       else
1727         {
1728           if (offset == 0)
1729             CLRC;
1730           emitcode ("clr", "a");
1731           emitcode ("subb", "a,%s", l);
1732         }
1733       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1734     }
1735   _endLazyDPSEvaluation ();
1736
1737   /* if any remaining bytes in the result */
1738   /* we just need to propagate the sign   */
1739   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1740     {
1741       emitcode ("rlc", "a");
1742       emitcode ("subb", "a,acc");
1743       while (size--)
1744         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1745     }
1746
1747 release:
1748   /* release the aops */
1749   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1750   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1751 }
1752
1753 /*-----------------------------------------------------------------*/
1754 /* saveRegisters - will look for a call and save the registers     */
1755 /*-----------------------------------------------------------------*/
1756 static void
1757 saveRegisters (iCode * lic)
1758 {
1759   int i;
1760   iCode *ic;
1761   bitVect *rsave;
1762   sym_link *detype;
1763
1764   /* look for call */
1765   for (ic = lic; ic; ic = ic->next)
1766     if (ic->op == CALL || ic->op == PCALL)
1767       break;
1768
1769   if (!ic)
1770     {
1771       fprintf (stderr, "found parameter push with no function call\n");
1772       return;
1773     }
1774
1775   /* if the registers have been saved already then
1776      do nothing */
1777   if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1778       IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1779     return;
1780
1781   /* find the registers in use at this time
1782      and push them away to safety */
1783   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1784                          ic->rUsed);
1785
1786   ic->regsSaved = 1;
1787   if (options.useXstack)
1788     {
1789       if (bitVectBitValue (rsave, R0_IDX))
1790         emitcode ("mov", "b,r0");
1791       emitcode ("mov", "r0,%s", spname);
1792       for (i = 0; i < ds390_nRegs; i++)
1793         {
1794           if (bitVectBitValue (rsave, i))
1795             {
1796               if (i == R0_IDX)
1797                 emitcode ("mov", "a,b");
1798               else
1799                 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1800               emitcode ("movx", "@r0,a");
1801               emitcode ("inc", "r0");
1802             }
1803         }
1804       emitcode ("mov", "%s,r0", spname);
1805       if (bitVectBitValue (rsave, R0_IDX))
1806         emitcode ("mov", "r0,b");
1807     }
1808   else
1809     for (i = 0; i < ds390_nRegs; i++)
1810       {
1811         if (bitVectBitValue (rsave, i))
1812           emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1813       }
1814
1815   detype = getSpec (operandType (IC_LEFT (ic)));
1816 }
1817
1818 /*-----------------------------------------------------------------*/
1819 /* unsaveRegisters - pop the pushed registers                      */
1820 /*-----------------------------------------------------------------*/
1821 static void
1822 unsaveRegisters (iCode * ic)
1823 {
1824   int i;
1825   bitVect *rsave;
1826   /* find the registers in use at this time
1827      and push them away to safety */
1828   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1829                          ic->rUsed);
1830
1831   if (options.useXstack)
1832     {
1833       emitcode ("mov", "r0,%s", spname);
1834       for (i = ds390_nRegs; i >= 0; i--)
1835         {
1836           if (bitVectBitValue (rsave, i))
1837             {
1838               emitcode ("dec", "r0");
1839               emitcode ("movx", "a,@r0");
1840               if (i == R0_IDX)
1841                 emitcode ("mov", "b,a");
1842               else
1843                 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1844             }
1845
1846         }
1847       emitcode ("mov", "%s,r0", spname);
1848       if (bitVectBitValue (rsave, R0_IDX))
1849         emitcode ("mov", "r0,b");
1850     }
1851   else
1852     for (i = ds390_nRegs; i >= 0; i--)
1853       {
1854         if (bitVectBitValue (rsave, i))
1855           emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1856       }
1857
1858 }
1859
1860
1861 /*-----------------------------------------------------------------*/
1862 /* pushSide -                */
1863 /*-----------------------------------------------------------------*/
1864 static void
1865 pushSide (operand * oper, int size)
1866 {
1867   int offset = 0;
1868   _startLazyDPSEvaluation ();
1869   while (size--)
1870     {
1871       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1872       if (AOP_TYPE (oper) != AOP_REG &&
1873           AOP_TYPE (oper) != AOP_DIR &&
1874           strcmp (l, "a"))
1875         {
1876           emitcode ("mov", "a,%s", l);
1877           emitcode ("push", "acc");
1878         }
1879       else
1880         emitcode ("push", "%s", l);
1881     }
1882   _endLazyDPSEvaluation ();
1883 }
1884
1885 /*-----------------------------------------------------------------*/
1886 /* assignResultValue -               */
1887 /*-----------------------------------------------------------------*/
1888 static void
1889 assignResultValue (operand * oper)
1890 {
1891   int offset = 0;
1892   int size = AOP_SIZE (oper);
1893
1894   _startLazyDPSEvaluation ();
1895   while (size--)
1896     {
1897       aopPut (AOP (oper), fReturn[offset], offset);
1898       offset++;
1899     }
1900   _endLazyDPSEvaluation ();
1901 }
1902
1903
1904 /*-----------------------------------------------------------------*/
1905 /* genXpush - pushes onto the external stack                       */
1906 /*-----------------------------------------------------------------*/
1907 static void
1908 genXpush (iCode * ic)
1909 {
1910   asmop *aop = newAsmop (0);
1911   regs *r;
1912   int size, offset = 0;
1913
1914   D (emitcode (";", "genXpush ");
1915     );
1916
1917   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1918   r = getFreePtr (ic, &aop, FALSE);
1919
1920
1921   emitcode ("mov", "%s,_spx", r->name);
1922
1923   size = AOP_SIZE (IC_LEFT (ic));
1924   _startLazyDPSEvaluation ();
1925   while (size--)
1926     {
1927
1928       char *l = aopGet (AOP (IC_LEFT (ic)),
1929                         offset++, FALSE, FALSE, TRUE);
1930       MOVA (l);
1931       emitcode ("movx", "@%s,a", r->name);
1932       emitcode ("inc", "%s", r->name);
1933
1934     }
1935   _endLazyDPSEvaluation ();
1936
1937
1938   emitcode ("mov", "_spx,%s", r->name);
1939
1940   freeAsmop (NULL, aop, ic, TRUE);
1941   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1942 }
1943
1944 /*-----------------------------------------------------------------*/
1945 /* genIpush - genrate code for pushing this gets a little complex  */
1946 /*-----------------------------------------------------------------*/
1947 static void
1948 genIpush (iCode * ic)
1949 {
1950   int size, offset = 0;
1951   char *l;
1952
1953   D (emitcode (";", "genIpush ");
1954     );
1955
1956   /* if this is not a parm push : ie. it is spill push
1957      and spill push is always done on the local stack */
1958   if (!ic->parmPush)
1959     {
1960
1961       /* and the item is spilt then do nothing */
1962       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1963         return;
1964
1965       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1966       size = AOP_SIZE (IC_LEFT (ic));
1967       /* push it on the stack */
1968       _startLazyDPSEvaluation ();
1969       while (size--)
1970         {
1971           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1972           if (*l == '#')
1973             {
1974               MOVA (l);
1975               l = "acc";
1976             }
1977           emitcode ("push", "%s", l);
1978         }
1979       _endLazyDPSEvaluation ();
1980       return;
1981     }
1982
1983   /* this is a paramter push: in this case we call
1984      the routine to find the call and save those
1985      registers that need to be saved */
1986   saveRegisters (ic);
1987
1988   /* if use external stack then call the external
1989      stack pushing routine */
1990   if (options.useXstack)
1991     {
1992       genXpush (ic);
1993       return;
1994     }
1995
1996   /* then do the push */
1997   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1998
1999   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2000   size = AOP_SIZE (IC_LEFT (ic));
2001
2002   _startLazyDPSEvaluation ();
2003   while (size--)
2004     {
2005       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2006       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2007           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2008           strcmp (l, "a"))
2009         {
2010           emitcode ("mov", "a,%s", l);
2011           emitcode ("push", "acc");
2012         }
2013       else
2014         emitcode ("push", "%s", l);
2015     }
2016   _endLazyDPSEvaluation ();
2017
2018   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2019 }
2020
2021 /*-----------------------------------------------------------------*/
2022 /* genIpop - recover the registers: can happen only for spilling   */
2023 /*-----------------------------------------------------------------*/
2024 static void
2025 genIpop (iCode * ic)
2026 {
2027   int size, offset;
2028
2029   D (emitcode (";", "genIpop ");
2030     );
2031
2032
2033   /* if the temp was not pushed then */
2034   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2035     return;
2036
2037   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2038   size = AOP_SIZE (IC_LEFT (ic));
2039   offset = (size - 1);
2040   _startLazyDPSEvaluation ();
2041   while (size--)
2042     {
2043       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2044                                      FALSE, TRUE, TRUE));
2045     }
2046   _endLazyDPSEvaluation ();
2047
2048   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2049 }
2050
2051 /*-----------------------------------------------------------------*/
2052 /* unsaveRBank - restores the resgister bank from stack            */
2053 /*-----------------------------------------------------------------*/
2054 static void
2055 unsaveRBank (int bank, iCode * ic, bool popPsw)
2056 {
2057   int i;
2058   asmop *aop = NULL;
2059   regs *r = NULL;
2060
2061   if (options.useXstack)
2062   {
2063       if (!ic)
2064       {
2065           /* Assume r0 is available for use. */
2066           r = ds390_regWithIdx (R0_IDX);;          
2067       } 
2068       else
2069       {
2070           aop = newAsmop (0);
2071           r = getFreePtr (ic, &aop, FALSE);
2072       }
2073       emitcode ("mov", "%s,_spx", r->name);      
2074   }
2075   
2076   if (popPsw)
2077     {
2078       if (options.useXstack)
2079       {
2080           emitcode ("movx", "a,@%s", r->name);
2081           emitcode ("mov", "psw,a");
2082           emitcode ("dec", "%s", r->name);
2083         }
2084       else
2085       {
2086         emitcode ("pop", "psw");
2087       }
2088     }
2089
2090   for (i = (ds390_nRegs - 1); i >= 0; i--)
2091     {
2092       if (options.useXstack)
2093         {
2094           emitcode ("movx", "a,@%s", r->name);
2095           emitcode ("mov", "(%s+%d),a",
2096                     regs390[i].base, 8 * bank + regs390[i].offset);
2097           emitcode ("dec", "%s", r->name);
2098
2099         }
2100       else
2101         emitcode ("pop", "(%s+%d)",
2102                   regs390[i].base, 8 * bank + regs390[i].offset);
2103     }
2104
2105   if (options.useXstack)
2106     {
2107       emitcode ("mov", "_spx,%s", r->name);
2108     }
2109     
2110   if (aop)
2111   {
2112       freeAsmop (NULL, aop, ic, TRUE);  
2113   }    
2114 }
2115
2116 /*-----------------------------------------------------------------*/
2117 /* saveRBank - saves an entire register bank on the stack          */
2118 /*-----------------------------------------------------------------*/
2119 static void
2120 saveRBank (int bank, iCode * ic, bool pushPsw)
2121 {
2122   int i;
2123   asmop *aop = NULL;
2124   regs *r = NULL;
2125
2126   if (options.useXstack)
2127     {
2128         if (!ic)
2129         {
2130           /* Assume r0 is available for use. */
2131                   r = ds390_regWithIdx (R0_IDX);;
2132         }
2133         else
2134         {
2135           aop = newAsmop (0);
2136           r = getFreePtr (ic, &aop, FALSE);
2137         }
2138         emitcode ("mov", "%s,_spx", r->name);    
2139     }
2140
2141   for (i = 0; i < ds390_nRegs; i++)
2142     {
2143       if (options.useXstack)
2144         {
2145           emitcode ("inc", "%s", r->name);
2146           emitcode ("mov", "a,(%s+%d)",
2147                     regs390[i].base, 8 * bank + regs390[i].offset);
2148           emitcode ("movx", "@%s,a", r->name);
2149         }
2150       else
2151         emitcode ("push", "(%s+%d)",
2152                   regs390[i].base, 8 * bank + regs390[i].offset);
2153     }
2154
2155   if (pushPsw)
2156     {
2157       if (options.useXstack)
2158         {
2159           emitcode ("mov", "a,psw");
2160           emitcode ("movx", "@%s,a", r->name);
2161           emitcode ("inc", "%s", r->name);
2162           emitcode ("mov", "_spx,%s", r->name);
2163         }
2164       else
2165       {
2166         emitcode ("push", "psw");
2167       }
2168
2169       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2170     }
2171   
2172   if (aop)
2173   {
2174        freeAsmop (NULL, aop, ic, TRUE);
2175   }    
2176     
2177   if (ic)
2178   {  
2179       ic->bankSaved = 1;
2180   }
2181 }
2182
2183 /*-----------------------------------------------------------------*/
2184 /* genCall - generates a call statement                            */
2185 /*-----------------------------------------------------------------*/
2186 static void
2187 genCall (iCode * ic)
2188 {
2189   sym_link *dtype;
2190   bool restoreBank = FALSE;
2191   bool swapBanks = FALSE;
2192
2193   D (emitcode (";", "genCall "););
2194
2195   /* if we are calling a not _naked function that is not using
2196      the same register bank then we need to save the
2197      destination registers on the stack */
2198   dtype = operandType (IC_LEFT (ic));
2199   if (dtype && !IFFUNC_ISNAKED(dtype) &&
2200       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2201       IFFUNC_ISISR (currFunc->type))
2202   {
2203       if (!ic->bankSaved) 
2204       {
2205            /* This is unexpected; the bank should have been saved in
2206             * genFunction.
2207             */
2208            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2209            restoreBank = TRUE;
2210       }
2211       swapBanks = TRUE;
2212   }
2213   
2214     /* if caller saves & we have not saved then */
2215     if (!ic->regsSaved)
2216       saveRegisters (ic);
2217   
2218   /* if send set is not empty the assign */
2219   /* We've saved all the registers we care about;
2220   * therefore, we may clobber any register not used
2221   * in the calling convention (i.e. anything not in
2222   * fReturn.
2223   */
2224   if (_G.sendSet)
2225     {
2226       iCode *sic;
2227
2228       for (sic = setFirstItem (_G.sendSet); sic;
2229            sic = setNextItem (_G.sendSet))
2230         {
2231           int size, offset = 0;
2232
2233           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2234           size = AOP_SIZE (IC_LEFT (sic));
2235
2236           _startLazyDPSEvaluation ();
2237           while (size--)
2238             {
2239               char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2240                                 FALSE, FALSE, TRUE);
2241                 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2242                 {
2243                     emitcode("mov", "%s,%s", regs390[offset].name, l);
2244                 }
2245                 else if (strcmp (l, fReturn[offset]))
2246                 {
2247                     emitcode ("mov", "%s,%s",
2248                               fReturn[offset],
2249                               l);
2250                 }
2251               offset++;
2252             }
2253           _endLazyDPSEvaluation ();
2254           if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2255           {
2256               size = AOP_SIZE (IC_LEFT (sic));
2257               if (size)
2258               {
2259                  size--;
2260               }
2261               while (size)
2262               {
2263                    size--;
2264                    emitcode("mov", "%s,%s",
2265                                     fReturn[size], regs390[size].name);
2266               }
2267           }
2268           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2269         }
2270       _G.sendSet = NULL;
2271     }  
2272     
2273   if (swapBanks)
2274   {
2275         emitcode ("mov", "psw,#0x%02x", 
2276            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2277   }
2278
2279   /* make the call */
2280   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2281                             OP_SYMBOL (IC_LEFT (ic))->rname :
2282                             OP_SYMBOL (IC_LEFT (ic))->name));
2283
2284   if (swapBanks)
2285   {
2286        emitcode ("mov", "psw,#0x%02x", 
2287           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2288   }
2289
2290   /* if we need assign a result value */
2291   if ((IS_ITEMP (IC_RESULT (ic)) &&
2292        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2293         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2294       IS_TRUE_SYMOP (IC_RESULT (ic)))
2295     {
2296       if (isOperandInFarSpace (IC_RESULT (ic))
2297           && getSize (operandType (IC_RESULT (ic))) <= 2)
2298         {
2299           int size = getSize (operandType (IC_RESULT (ic)));
2300
2301           /* Special case for 1 or 2 byte return in far space. */
2302           MOVA (fReturn[0]);
2303           if (size > 1)
2304             {
2305               emitcode ("mov", "b,%s", fReturn[1]);
2306             }
2307
2308           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2309           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2310
2311           if (size > 1)
2312             {
2313               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2314             }
2315           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2316         }
2317       else
2318         {
2319           _G.accInUse++;
2320           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2321           _G.accInUse--;
2322
2323           assignResultValue (IC_RESULT (ic));
2324
2325           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2326         }
2327     }
2328
2329   /* adjust the stack for parameters if
2330      required */
2331   if (ic->parmBytes)
2332     {
2333       int i;
2334       if (ic->parmBytes > 3)
2335         {
2336           emitcode ("mov", "a,%s", spname);
2337           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2338           emitcode ("mov", "%s,a", spname);
2339         }
2340       else
2341         for (i = 0; i < ic->parmBytes; i++)
2342           emitcode ("dec", "%s", spname);
2343     }
2344
2345   /* if we hade saved some registers then unsave them */
2346   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2347     unsaveRegisters (ic);
2348
2349   /* if register bank was saved then pop them */
2350   if (restoreBank)
2351     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2352 }
2353
2354 /*-----------------------------------------------------------------*/
2355 /* genPcall - generates a call by pointer statement                */
2356 /*-----------------------------------------------------------------*/
2357 static void
2358 genPcall (iCode * ic)
2359 {
2360   sym_link *dtype;
2361   symbol *rlbl = newiTempLabel (NULL);
2362
2363   D (emitcode (";", "genPcall ");
2364     );
2365
2366
2367   /* if caller saves & we have not saved then */
2368   if (!ic->regsSaved)
2369     saveRegisters (ic);
2370
2371   /* if we are calling a function that is not using
2372      the same register bank then we need to save the
2373      destination registers on the stack */
2374   dtype = operandType (IC_LEFT (ic));
2375   if (dtype &&
2376       IFFUNC_ISISR (currFunc->type) &&
2377       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)))
2378     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2379
2380
2381   /* push the return address on to the stack */
2382   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2383   emitcode ("push", "acc");
2384   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2385   emitcode ("push", "acc");
2386
2387   if (options.model == MODEL_FLAT24)
2388     {
2389       emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2390       emitcode ("push", "acc");
2391     }
2392
2393   /* now push the calling address */
2394   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2395
2396   pushSide (IC_LEFT (ic), FPTRSIZE);
2397
2398   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2399
2400   /* if send set is not empty the assign */
2401   if (_G.sendSet)
2402     {
2403       iCode *sic;
2404
2405       for (sic = setFirstItem (_G.sendSet); sic;
2406            sic = setNextItem (_G.sendSet))
2407         {
2408           int size, offset = 0;
2409
2410           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2411           size = AOP_SIZE (IC_LEFT (sic));
2412           _startLazyDPSEvaluation ();
2413           while (size--)
2414             {
2415               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2416                                 FALSE, FALSE, TRUE);
2417               if (strcmp (l, fReturn[offset]))
2418                 {
2419                   emitcode ("mov", "%s,%s",
2420                             fReturn[offset],
2421                             l);
2422                 }
2423               offset++;
2424             }
2425           _endLazyDPSEvaluation ();
2426           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2427         }
2428       _G.sendSet = NULL;
2429     }
2430
2431   emitcode ("ret", "");
2432   emitcode ("", "%05d$:", (rlbl->key + 100));
2433
2434
2435   /* if we need assign a result value */
2436   if ((IS_ITEMP (IC_RESULT (ic)) &&
2437        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2438         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2439       IS_TRUE_SYMOP (IC_RESULT (ic)))
2440     {
2441
2442       _G.accInUse++;
2443       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2444       _G.accInUse--;
2445
2446       assignResultValue (IC_RESULT (ic));
2447
2448       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2449     }
2450
2451   /* adjust the stack for parameters if
2452      required */
2453   if (ic->parmBytes)
2454     {
2455       int i;
2456       if (ic->parmBytes > 3)
2457         {
2458           emitcode ("mov", "a,%s", spname);
2459           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2460           emitcode ("mov", "%s,a", spname);
2461         }
2462       else
2463         for (i = 0; i < ic->parmBytes; i++)
2464           emitcode ("dec", "%s", spname);
2465
2466     }
2467
2468   /* if register bank was saved then unsave them */
2469   if (dtype &&
2470       (FUNC_REGBANK (currFunc->type) !=
2471        FUNC_REGBANK (dtype)))
2472     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2473
2474   /* if we hade saved some registers then
2475      unsave them */
2476   if (ic->regsSaved)
2477     unsaveRegisters (ic);
2478
2479 }
2480
2481 /*-----------------------------------------------------------------*/
2482 /* resultRemat - result  is rematerializable                       */
2483 /*-----------------------------------------------------------------*/
2484 static int
2485 resultRemat (iCode * ic)
2486 {
2487   if (SKIP_IC (ic) || ic->op == IFX)
2488     return 0;
2489
2490   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2491     {
2492       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2493       if (sym->remat && !POINTER_SET (ic))
2494         return 1;
2495     }
2496
2497   return 0;
2498 }
2499
2500 #if defined(__BORLANDC__) || defined(_MSC_VER)
2501 #define STRCASECMP stricmp
2502 #else
2503 #define STRCASECMP strcasecmp
2504 #endif
2505
2506 /*-----------------------------------------------------------------*/
2507 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2508 /*-----------------------------------------------------------------*/
2509 static bool
2510 inExcludeList (char *s)
2511 {
2512   int i = 0;
2513
2514   if (options.excludeRegs[i] &&
2515       STRCASECMP (options.excludeRegs[i], "none") == 0)
2516     return FALSE;
2517
2518   for (i = 0; options.excludeRegs[i]; i++)
2519     {
2520       if (options.excludeRegs[i] &&
2521           STRCASECMP (s, options.excludeRegs[i]) == 0)
2522         return TRUE;
2523     }
2524   return FALSE;
2525 }
2526
2527 /*-----------------------------------------------------------------*/
2528 /* genFunction - generated code for function entry                 */
2529 /*-----------------------------------------------------------------*/
2530 static void
2531 genFunction (iCode * ic)
2532 {
2533   symbol *sym;
2534   sym_link *ftype;
2535   bool   switchedPSW = FALSE;
2536
2537   D (emitcode (";", "genFunction "););
2538
2539   _G.nRegsSaved = 0;
2540   /* create the function header */
2541   emitcode (";", "-----------------------------------------");
2542   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2543   emitcode (";", "-----------------------------------------");
2544
2545   emitcode ("", "%s:", sym->rname);
2546   ftype = operandType (IC_LEFT (ic));
2547
2548   if (IFFUNC_ISNAKED(ftype))
2549   {
2550       emitcode(";", "naked function: no prologue.");
2551       return;
2552   }
2553
2554   /* if critical function then turn interrupts off */
2555   if (IFFUNC_ISCRITICAL (ftype))
2556     emitcode ("clr", "ea");
2557
2558   /* here we need to generate the equates for the
2559      register bank if required */
2560   if (FUNC_REGBANK (ftype) != rbank)
2561     {
2562       int i;
2563
2564       rbank = FUNC_REGBANK (ftype);
2565       for (i = 0; i < ds390_nRegs; i++)
2566         {
2567           if (strcmp (regs390[i].base, "0") == 0)
2568             emitcode ("", "%s = 0x%02x",
2569                       regs390[i].dname,
2570                       8 * rbank + regs390[i].offset);
2571           else
2572             emitcode ("", "%s = %s + 0x%02x",
2573                       regs390[i].dname,
2574                       regs390[i].base,
2575                       8 * rbank + regs390[i].offset);
2576         }
2577     }
2578
2579   /* if this is an interrupt service routine then
2580      save acc, b, dpl, dph  */
2581   if (IFFUNC_ISISR (sym->type))
2582     {
2583
2584       if (!inExcludeList ("acc"))
2585         emitcode ("push", "acc");
2586       if (!inExcludeList ("b"))
2587         emitcode ("push", "b");
2588       if (!inExcludeList ("dpl"))
2589         emitcode ("push", "dpl");
2590       if (!inExcludeList ("dph"))
2591         emitcode ("push", "dph");
2592       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2593         {
2594           emitcode ("push", "dpx");
2595           /* Make sure we're using standard DPTR */
2596           emitcode ("push", "dps");
2597           emitcode ("mov", "dps, #0x00");
2598           if (options.stack10bit)
2599             {
2600               /* This ISR could conceivably use DPTR2. Better save it. */
2601               emitcode ("push", "dpl1");
2602               emitcode ("push", "dph1");
2603               emitcode ("push", "dpx1");
2604               emitcode ("push",  DP2_RESULT_REG);
2605             }
2606         }
2607       /* if this isr has no bank i.e. is going to
2608          run with bank 0 , then we need to save more
2609          registers :-) */
2610       if (!FUNC_REGBANK (sym->type))
2611         {
2612
2613           /* if this function does not call any other
2614              function then we can be economical and
2615              save only those registers that are used */
2616           if (!IFFUNC_HASFCALL(sym->type))
2617             {
2618               int i;
2619
2620               /* if any registers used */
2621               if (sym->regsUsed)
2622                 {
2623                   /* save the registers used */
2624                   for (i = 0; i < sym->regsUsed->size; i++)
2625                     {
2626                       if (bitVectBitValue (sym->regsUsed, i) ||
2627                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2628                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2629                     }
2630                 }
2631
2632             }
2633           else
2634             {
2635               /* this function has  a function call cannot
2636                  determines register usage so we will have to push the
2637                  entire bank */
2638               saveRBank (0, ic, FALSE);
2639             }
2640         }
2641         else
2642         {
2643             /* This ISR uses a non-zero bank.
2644              *
2645              * We assume that the bank is available for our
2646              * exclusive use.
2647              *
2648              * However, if this ISR calls a function which uses some
2649              * other bank, we must save that bank entirely.
2650              */
2651             unsigned long banksToSave = 0;
2652             
2653             if (IFFUNC_HASFCALL(sym->type))
2654             {
2655
2656 #define MAX_REGISTER_BANKS 4
2657
2658                 iCode *i;
2659                 int ix;
2660
2661                 for (i = ic; i; i = i->next)
2662                 {
2663                     if (i->op == ENDFUNCTION)
2664                     {
2665                         /* we got to the end OK. */
2666                         break;
2667                     }
2668                     
2669                     if (i->op == CALL)
2670                     {
2671                         sym_link *dtype;
2672                         
2673                         dtype = operandType (IC_LEFT(i));
2674                         if (dtype 
2675                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2676                         {
2677                              /* Mark this bank for saving. */
2678                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2679                              {
2680                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2681                              }
2682                              else
2683                              {
2684                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2685                              }
2686                              
2687                              /* And note that we don't need to do it in 
2688                               * genCall.
2689                               */
2690                              i->bankSaved = 1;
2691                         }
2692                     }
2693                     if (i->op == PCALL)
2694                     {
2695                         /* This is a mess; we have no idea what
2696                          * register bank the called function might
2697                          * use.
2698                          *
2699                          * The only thing I can think of to do is
2700                          * throw a warning and hope.
2701                          */
2702                         werror(W_FUNCPTR_IN_USING_ISR);   
2703                     }
2704                 }
2705
2706                 if (banksToSave && options.useXstack)
2707                 {
2708                     /* Since we aren't passing it an ic, 
2709                      * saveRBank will assume r0 is available to abuse.
2710                      *
2711                      * So switch to our (trashable) bank now, so
2712                      * the caller's R0 isn't trashed.
2713                      */
2714                     emitcode ("push", "psw");
2715                     emitcode ("mov", "psw,#0x%02x", 
2716                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2717                     switchedPSW = TRUE;
2718                 }
2719                 
2720                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2721                 {
2722                      if (banksToSave & (1 << ix))
2723                      {
2724                          saveRBank(ix, NULL, FALSE);
2725                      }
2726                 }
2727             }
2728             // jwk: this needs a closer look
2729             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2730         }
2731     }
2732   else
2733     {
2734       /* if callee-save to be used for this function
2735          then save the registers being used in this function */
2736       if (IFFUNC_CALLEESAVES(sym->type))
2737         {
2738           int i;
2739
2740           /* if any registers used */
2741           if (sym->regsUsed)
2742             {
2743               /* save the registers used */
2744               for (i = 0; i < sym->regsUsed->size; i++)
2745                 {
2746                   if (bitVectBitValue (sym->regsUsed, i) ||
2747                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2748                     {
2749                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2750                       _G.nRegsSaved++;
2751                     }
2752                 }
2753             }
2754         }
2755     }
2756
2757   /* set the register bank to the desired value */
2758   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2759    && !switchedPSW)
2760     {
2761       emitcode ("push", "psw");
2762       emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2763     }
2764
2765   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2766     {
2767
2768       if (options.useXstack)
2769         {
2770           emitcode ("mov", "r0,%s", spname);
2771           emitcode ("mov", "a,_bp");
2772           emitcode ("movx", "@r0,a");
2773           emitcode ("inc", "%s", spname);
2774         }
2775       else
2776         {
2777           /* set up the stack */
2778           emitcode ("push", "_bp");     /* save the callers stack  */
2779         }
2780       emitcode ("mov", "_bp,%s", spname);
2781     }
2782
2783   /* adjust the stack for the function */
2784   if (sym->stack)
2785     {
2786
2787       int i = sym->stack;
2788       if (i > 256)
2789         werror (W_STACK_OVERFLOW, sym->name);
2790
2791       if (i > 3 && sym->recvSize < 4)
2792         {
2793
2794           emitcode ("mov", "a,sp");
2795           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2796           emitcode ("mov", "sp,a");
2797
2798         }
2799       else
2800         while (i--)
2801           emitcode ("inc", "sp");
2802     }
2803
2804   if (sym->xstack)
2805     {
2806
2807       emitcode ("mov", "a,_spx");
2808       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2809       emitcode ("mov", "_spx,a");
2810     }
2811
2812 }
2813
2814 /*-----------------------------------------------------------------*/
2815 /* genEndFunction - generates epilogue for functions               */
2816 /*-----------------------------------------------------------------*/
2817 static void
2818 genEndFunction (iCode * ic)
2819 {
2820   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2821
2822   D (emitcode (";", "genEndFunction "););
2823
2824   if (IFFUNC_ISNAKED(sym->type))
2825   {
2826       emitcode(";", "naked function: no epilogue.");
2827       return;
2828   }
2829
2830   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2831     {
2832       emitcode ("mov", "%s,_bp", spname);
2833     }
2834
2835   /* if use external stack but some variables were
2836      added to the local stack then decrement the
2837      local stack */
2838   if (options.useXstack && sym->stack)
2839     {
2840       emitcode ("mov", "a,sp");
2841       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2842       emitcode ("mov", "sp,a");
2843     }
2844
2845
2846   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2847     {
2848       if (options.useXstack)
2849         {
2850           emitcode ("mov", "r0,%s", spname);
2851           emitcode ("movx", "a,@r0");
2852           emitcode ("mov", "_bp,a");
2853           emitcode ("dec", "%s", spname);
2854         }
2855       else
2856         {
2857           emitcode ("pop", "_bp");
2858         }
2859     }
2860
2861   /* restore the register bank  */
2862   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2863   {
2864     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2865      || !options.useXstack)
2866     {
2867         /* Special case of ISR using non-zero bank with useXstack
2868          * is handled below.
2869          */
2870         emitcode ("pop", "psw");
2871     }
2872   }
2873
2874   if (IFFUNC_ISISR (sym->type))
2875     {
2876
2877       /* now we need to restore the registers */
2878       /* if this isr has no bank i.e. is going to
2879          run with bank 0 , then we need to save more
2880          registers :-) */
2881       if (!FUNC_REGBANK (sym->type))
2882         {
2883           /* if this function does not call any other
2884              function then we can be economical and
2885              save only those registers that are used */
2886           if (!IFFUNC_HASFCALL(sym->type))
2887             {
2888               int i;
2889
2890               /* if any registers used */
2891               if (sym->regsUsed)
2892                 {
2893                   /* save the registers used */
2894                   for (i = sym->regsUsed->size; i >= 0; i--)
2895                     {
2896                       if (bitVectBitValue (sym->regsUsed, i) ||
2897                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2898                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2899                     }
2900                 }
2901
2902             }
2903           else
2904             {
2905               /* this function has  a function call cannot
2906                  determines register usage so we will have to pop the
2907                  entire bank */
2908               unsaveRBank (0, ic, FALSE);
2909             }
2910         }
2911         else
2912         {
2913             /* This ISR uses a non-zero bank.
2914              *
2915              * Restore any register banks saved by genFunction
2916              * in reverse order.
2917              */
2918           // jwk: this needs a closer look
2919             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2920             int ix;
2921           
2922             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2923             {
2924                 if (savedBanks & (1 << ix))
2925                 {
2926                     unsaveRBank(ix, NULL, FALSE);
2927                 }
2928             }
2929             
2930             if (options.useXstack)
2931             {
2932                 /* Restore bank AFTER calling unsaveRBank,
2933                  * since it can trash r0.
2934                  */
2935                 emitcode ("pop", "psw");
2936             }
2937         }
2938
2939       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2940         {
2941           if (options.stack10bit)
2942             {
2943               emitcode ("pop", DP2_RESULT_REG);
2944               emitcode ("pop", "dpx1");
2945               emitcode ("pop", "dph1");
2946               emitcode ("pop", "dpl1");
2947             }
2948           emitcode ("pop", "dps");
2949           emitcode ("pop", "dpx");
2950         }
2951       if (!inExcludeList ("dph"))
2952         emitcode ("pop", "dph");
2953       if (!inExcludeList ("dpl"))
2954         emitcode ("pop", "dpl");
2955       if (!inExcludeList ("b"))
2956         emitcode ("pop", "b");
2957       if (!inExcludeList ("acc"))
2958         emitcode ("pop", "acc");
2959
2960       if (IFFUNC_ISCRITICAL (sym->type))
2961         emitcode ("setb", "ea");
2962
2963       /* if debug then send end of function */
2964       if (options.debug && currFunc) {
2965           _G.debugLine = 1;
2966           emitcode ("", "C$%s$%d$%d$%d ==.",
2967                     FileBaseName (ic->filename), currFunc->lastLine,
2968                     ic->level, ic->block);
2969           if (IS_STATIC (currFunc->etype))
2970             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2971           else
2972             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2973           _G.debugLine = 0;
2974         }
2975
2976       emitcode ("reti", "");
2977     }
2978   else
2979     {
2980       if (IFFUNC_ISCRITICAL (sym->type))
2981         emitcode ("setb", "ea");
2982
2983       if (IFFUNC_CALLEESAVES(sym->type))
2984         {
2985           int i;
2986
2987           /* if any registers used */
2988           if (sym->regsUsed)
2989             {
2990               /* save the registers used */
2991               for (i = sym->regsUsed->size; i >= 0; i--)
2992                 {
2993                   if (bitVectBitValue (sym->regsUsed, i) ||
2994                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2995                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2996                 }
2997             }
2998
2999         }
3000
3001       /* if debug then send end of function */
3002       if (options.debug && currFunc)
3003         {
3004           _G.debugLine = 1;
3005           emitcode ("", "C$%s$%d$%d$%d ==.",
3006                     FileBaseName (ic->filename), currFunc->lastLine,
3007                     ic->level, ic->block);
3008           if (IS_STATIC (currFunc->etype))
3009             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3010           else
3011             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3012           _G.debugLine = 0;
3013         }
3014
3015       emitcode ("ret", "");
3016     }
3017
3018 }
3019
3020 /*-----------------------------------------------------------------*/
3021 /* genRet - generate code for return statement                     */
3022 /*-----------------------------------------------------------------*/
3023 static void
3024 genRet (iCode * ic)
3025 {
3026   int size, offset = 0, pushed = 0;
3027
3028   D (emitcode (";", "genRet ");
3029     );
3030
3031   /* if we have no return value then
3032      just generate the "ret" */
3033   if (!IC_LEFT (ic))
3034     goto jumpret;
3035
3036   /* we have something to return then
3037      move the return value into place */
3038   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3039   size = AOP_SIZE (IC_LEFT (ic));
3040
3041   _startLazyDPSEvaluation ();
3042   while (size--)
3043     {
3044       char *l;
3045       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3046         {
3047           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3048                       FALSE, TRUE, FALSE);
3049           emitcode ("push", "%s", l);
3050           pushed++;
3051         }
3052       else
3053         {
3054           /* Since A is the last element of fReturn,
3055            * is is OK to clobber it in the aopGet.
3056            */
3057           l = aopGet (AOP (IC_LEFT (ic)), offset,
3058                       FALSE, FALSE, TRUE);
3059           if (strcmp (fReturn[offset], l))
3060             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3061         }
3062     }
3063   _endLazyDPSEvaluation ();
3064
3065   if (pushed)
3066     {
3067       while (pushed)
3068         {
3069           pushed--;
3070           if (strcmp (fReturn[pushed], "a"))
3071             emitcode ("pop", fReturn[pushed]);
3072           else
3073             emitcode ("pop", "acc");
3074         }
3075     }
3076   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3077
3078 jumpret:
3079   /* generate a jump to the return label
3080      if the next is not the return statement */
3081   if (!(ic->next && ic->next->op == LABEL &&
3082         IC_LABEL (ic->next) == returnLabel))
3083
3084     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3085
3086 }
3087
3088 /*-----------------------------------------------------------------*/
3089 /* genLabel - generates a label                                    */
3090 /*-----------------------------------------------------------------*/
3091 static void
3092 genLabel (iCode * ic)
3093 {
3094   /* special case never generate */
3095   if (IC_LABEL (ic) == entryLabel)
3096     return;
3097
3098   D (emitcode (";", "genLabel ");
3099     );
3100
3101   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3102 }
3103
3104 /*-----------------------------------------------------------------*/
3105 /* genGoto - generates a ljmp                                      */
3106 /*-----------------------------------------------------------------*/
3107 static void
3108 genGoto (iCode * ic)
3109 {
3110   D (emitcode (";", "genGoto ");
3111     );
3112   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3113 }
3114
3115 /*-----------------------------------------------------------------*/
3116 /* findLabelBackwards: walks back through the iCode chain looking  */
3117 /* for the given label. Returns number of iCode instructions     */
3118 /* between that label and given ic.          */
3119 /* Returns zero if label not found.          */
3120 /*-----------------------------------------------------------------*/
3121 static int
3122 findLabelBackwards (iCode * ic, int key)
3123 {
3124   int count = 0;
3125
3126   while (ic->prev)
3127     {
3128       ic = ic->prev;
3129       count++;
3130
3131       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3132         {
3133           /* printf("findLabelBackwards = %d\n", count); */
3134           return count;
3135         }
3136     }
3137
3138   return 0;
3139 }
3140
3141 /*-----------------------------------------------------------------*/
3142 /* genPlusIncr :- does addition with increment if possible         */
3143 /*-----------------------------------------------------------------*/
3144 static bool
3145 genPlusIncr (iCode * ic)
3146 {
3147   unsigned int icount;
3148   unsigned int size = getDataSize (IC_RESULT (ic));
3149
3150   /* will try to generate an increment */
3151   /* if the right side is not a literal
3152      we cannot */
3153   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3154     return FALSE;
3155
3156   /* if the literal value of the right hand side
3157      is greater than 4 then it is not worth it */
3158   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3159     return FALSE;
3160
3161   /* if increment 16 bits in register */
3162   if (
3163        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3164        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3165        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3166        (size > 1) &&
3167        (icount == 1))
3168     {
3169       symbol *tlbl;
3170       int emitTlbl;
3171       int labelRange;
3172
3173       /* If the next instruction is a goto and the goto target
3174        * is <= 5 instructions previous to this, we can generate
3175        * jumps straight to that target.
3176        */
3177       if (ic->next && ic->next->op == GOTO
3178           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3179           && labelRange <= 5)
3180         {
3181           emitcode (";", "tail increment optimized (range %d)", labelRange);
3182           tlbl = IC_LABEL (ic->next);
3183           emitTlbl = 0;
3184         }
3185       else
3186         {
3187           tlbl = newiTempLabel (NULL);
3188           emitTlbl = 1;
3189         }
3190       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3191       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3192           IS_AOP_PREG (IC_RESULT (ic)))
3193         emitcode ("cjne", "%s,#0x00,%05d$"
3194                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3195                   ,tlbl->key + 100);
3196       else
3197         {
3198           emitcode ("clr", "a");
3199           emitcode ("cjne", "a,%s,%05d$"
3200                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3201                     ,tlbl->key + 100);
3202         }
3203
3204       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3205       if (size > 2)
3206         {
3207           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3208               IS_AOP_PREG (IC_RESULT (ic)))
3209             emitcode ("cjne", "%s,#0x00,%05d$"
3210                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3211                       ,tlbl->key + 100);
3212           else
3213             emitcode ("cjne", "a,%s,%05d$"
3214                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3215                       ,tlbl->key + 100);
3216
3217           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3218         }
3219       if (size > 3)
3220         {
3221           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3222               IS_AOP_PREG (IC_RESULT (ic)))
3223             emitcode ("cjne", "%s,#0x00,%05d$"
3224                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3225                       ,tlbl->key + 100);
3226           else
3227             {
3228               emitcode ("cjne", "a,%s,%05d$"
3229                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3230                         ,tlbl->key + 100);
3231             }
3232           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3233         }
3234
3235       if (emitTlbl)
3236         {
3237           emitcode ("", "%05d$:", tlbl->key + 100);
3238         }
3239       return TRUE;
3240     }
3241
3242   /* if the sizes are greater than 1 then we cannot */
3243   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3244       AOP_SIZE (IC_LEFT (ic)) > 1)
3245     return FALSE;
3246
3247   /* we can if the aops of the left & result match or
3248      if they are in registers and the registers are the
3249      same */
3250   if (
3251        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3252        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3253        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3254     {
3255
3256       if (icount > 3)
3257         {
3258           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3259           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3260           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3261         }
3262       else
3263         {
3264
3265           _startLazyDPSEvaluation ();
3266           while (icount--)
3267             {
3268               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3269             }
3270           _endLazyDPSEvaluation ();
3271         }
3272
3273       return TRUE;
3274     }
3275
3276   return FALSE;
3277 }
3278
3279 /*-----------------------------------------------------------------*/
3280 /* outBitAcc - output a bit in acc                                 */
3281 /*-----------------------------------------------------------------*/
3282 static void
3283 outBitAcc (operand * result)
3284 {
3285   symbol *tlbl = newiTempLabel (NULL);
3286   /* if the result is a bit */
3287   if (AOP_TYPE (result) == AOP_CRY)
3288     {
3289       aopPut (AOP (result), "a", 0);
3290     }
3291   else
3292     {
3293       emitcode ("jz", "%05d$", tlbl->key + 100);
3294       emitcode ("mov", "a,%s", one);
3295       emitcode ("", "%05d$:", tlbl->key + 100);
3296       outAcc (result);
3297     }
3298 }
3299
3300 /*-----------------------------------------------------------------*/
3301 /* genPlusBits - generates code for addition of two bits           */
3302 /*-----------------------------------------------------------------*/
3303 static void
3304 genPlusBits (iCode * ic)
3305 {
3306   D (emitcode (";", "genPlusBits ");
3307     );
3308   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3309     {
3310       symbol *lbl = newiTempLabel (NULL);
3311       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3312       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3313       emitcode ("cpl", "c");
3314       emitcode ("", "%05d$:", (lbl->key + 100));
3315       outBitC (IC_RESULT (ic));
3316     }
3317   else
3318     {
3319       emitcode ("clr", "a");
3320       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3321       emitcode ("rlc", "a");
3322       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3323       emitcode ("addc", "a,#0x00");
3324       outAcc (IC_RESULT (ic));
3325     }
3326 }
3327
3328 static void
3329 adjustArithmeticResult (iCode * ic)
3330 {
3331   if (opIsGptr (IC_RESULT (ic)) &&
3332       opIsGptr (IC_LEFT (ic)) &&
3333       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3334     {
3335       aopPut (AOP (IC_RESULT (ic)),
3336               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3337               GPTRSIZE - 1);
3338     }
3339
3340   if (opIsGptr (IC_RESULT (ic)) &&
3341       opIsGptr (IC_RIGHT (ic)) &&
3342       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3343     {
3344       aopPut (AOP (IC_RESULT (ic)),
3345             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3346               GPTRSIZE - 1);
3347     }
3348
3349   if (opIsGptr (IC_RESULT (ic)) &&
3350       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3351       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3352       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3353       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3354     {
3355       char buffer[5];
3356       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3357       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3358     }
3359 }
3360
3361 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3362 // (because all three operands are in far space).
3363 #define AOP_OP_3(ic) \
3364     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3365     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3366     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3367               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3368     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3369         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3370     { \
3371         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3372         fprintf(stderr,                                  \
3373                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3374     }
3375
3376 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3377 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3378 // will be set TRUE. The caller must then handle the case specially, noting
3379 // that the IC_RESULT operand is not aopOp'd.
3380 #define AOP_OP_3_NOFATAL(ic, rc) \
3381     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3382     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3383     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3384         isOperandInFarSpace(IC_RESULT(ic))) \
3385     { \
3386        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3387        rc = TRUE; \
3388     }  \
3389     else \
3390     { \
3391        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3392                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3393        rc = FALSE; \
3394        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3395            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3396        { \
3397             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3398             fprintf(stderr,                                  \
3399                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3400        } \
3401     }
3402
3403 // aopOp the left & right operands of an ic.
3404 #define AOP_OP_2(ic) \
3405     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3406     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3407
3408 // convienience macro.
3409 #define AOP_SET_LOCALS(ic) \
3410     left = IC_LEFT(ic); \
3411     right = IC_RIGHT(ic); \
3412     result = IC_RESULT(ic);
3413
3414
3415 // Given an integer value of pushedSize bytes on the stack,
3416 // adjust it to be resultSize bytes, either by discarding
3417 // the most significant bytes or by zero-padding.
3418 //
3419 // On exit from this macro, pushedSize will have been adjusted to
3420 // equal resultSize, and ACC may be trashed.
3421 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3422       /* If the pushed data is bigger than the result,          \
3423        * simply discard unused bytes. Icky, but works.          \
3424        */                                                       \
3425       while (pushedSize > resultSize)                           \
3426       {                                                         \
3427           D (emitcode (";", "discarding unused result byte."););\
3428           emitcode ("pop", "acc");                              \
3429           pushedSize--;                                         \
3430       }                                                         \
3431       if (pushedSize < resultSize)                              \
3432       {                                                         \
3433           emitcode ("clr", "a");                                \
3434           /* Conversly, we haven't pushed enough here.          \
3435            * just zero-pad, and all is well.                    \
3436            */                                                   \
3437           while (pushedSize < resultSize)                       \
3438           {                                                     \
3439               emitcode("push", "acc");                          \
3440               pushedSize++;                                     \
3441           }                                                     \
3442       }                                                         \
3443       assert(pushedSize == resultSize);
3444
3445 /*-----------------------------------------------------------------*/
3446 /* genPlus - generates code for addition                           */
3447 /*-----------------------------------------------------------------*/
3448 static void
3449 genPlus (iCode * ic)
3450 {
3451   int size, offset = 0;
3452   bool pushResult = FALSE;
3453   int rSize;
3454
3455   D (emitcode (";", "genPlus "););
3456
3457   /* special cases :- */
3458
3459   AOP_OP_3_NOFATAL (ic, pushResult);
3460   if (pushResult)
3461     {
3462       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3463     }
3464
3465   if (!pushResult)
3466     {
3467       /* if literal, literal on the right or
3468          if left requires ACC or right is already
3469          in ACC */
3470       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3471        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3472           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3473         {
3474           operand *t = IC_RIGHT (ic);
3475           IC_RIGHT (ic) = IC_LEFT (ic);
3476           IC_LEFT (ic) = t;
3477           emitcode (";", "Swapped plus args.");
3478         }
3479
3480       /* if both left & right are in bit
3481          space */
3482       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3483           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3484         {
3485           genPlusBits (ic);
3486           goto release;
3487         }
3488
3489       /* if left in bit space & right literal */
3490       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3491           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3492         {
3493           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3494           /* if result in bit space */
3495           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3496             {
3497               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3498                 emitcode ("cpl", "c");
3499               outBitC (IC_RESULT (ic));
3500             }
3501           else
3502             {
3503               size = getDataSize (IC_RESULT (ic));
3504               _startLazyDPSEvaluation ();
3505               while (size--)
3506                 {
3507                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3508                   emitcode ("addc", "a,#00");
3509                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3510                 }
3511               _endLazyDPSEvaluation ();
3512             }
3513           goto release;
3514         }
3515
3516       /* if I can do an increment instead
3517          of add then GOOD for ME */
3518       if (genPlusIncr (ic) == TRUE)
3519         {
3520           emitcode (";", "did genPlusIncr");
3521           goto release;
3522         }
3523
3524     }
3525   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3526
3527   _startLazyDPSEvaluation ();
3528   while (size--)
3529     {
3530       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3531         {
3532           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3533           if (offset == 0)
3534             emitcode ("add", "a,%s",
3535                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3536           else
3537             emitcode ("addc", "a,%s",
3538                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3539         }
3540       else
3541         {
3542           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3543           {
3544               /* right is going to use ACC or we would have taken the
3545                * above branch.
3546                */
3547               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3548        TR_AP("#3");
3549               D(emitcode(";", "+ AOP_ACC special case."););
3550               emitcode("xch", "a, %s", DP2_RESULT_REG);
3551           }
3552           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3553           if (offset == 0)
3554           {
3555             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3556             {
3557          TR_AP("#4");
3558                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3559             }
3560             else
3561             {
3562                 emitcode ("add", "a,%s",
3563                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3564             }
3565           }
3566           else
3567           {
3568             emitcode ("addc", "a,%s",
3569                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3570           }
3571         }
3572       if (!pushResult)
3573         {
3574           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3575         }
3576       else
3577         {
3578           emitcode ("push", "acc");
3579         }
3580       offset++;
3581     }
3582   _endLazyDPSEvaluation ();
3583
3584   if (pushResult)
3585     {
3586       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3587
3588       size = getDataSize (IC_LEFT (ic));
3589       rSize = getDataSize (IC_RESULT (ic));
3590
3591       ADJUST_PUSHED_RESULT(size, rSize);
3592
3593       _startLazyDPSEvaluation ();
3594       while (size--)
3595         {
3596           emitcode ("pop", "acc");
3597           aopPut (AOP (IC_RESULT (ic)), "a", size);
3598         }
3599       _endLazyDPSEvaluation ();
3600     }
3601
3602   adjustArithmeticResult (ic);
3603
3604 release:
3605   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3606   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3607   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3608 }
3609
3610 /*-----------------------------------------------------------------*/
3611 /* genMinusDec :- does subtraction with deccrement if possible     */
3612 /*-----------------------------------------------------------------*/
3613 static bool
3614 genMinusDec (iCode * ic)
3615 {
3616   unsigned int icount;
3617   unsigned int size = getDataSize (IC_RESULT (ic));
3618
3619   /* will try to generate an increment */
3620   /* if the right side is not a literal
3621      we cannot */
3622   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3623     return FALSE;
3624
3625   /* if the literal value of the right hand side
3626      is greater than 4 then it is not worth it */
3627   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3628     return FALSE;
3629
3630   /* if decrement 16 bits in register */
3631   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3632       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3633       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3634       (size > 1) &&
3635       (icount == 1))
3636     {
3637       symbol *tlbl;
3638       int emitTlbl;
3639       int labelRange;
3640
3641       /* If the next instruction is a goto and the goto target
3642          * is <= 5 instructions previous to this, we can generate
3643          * jumps straight to that target.
3644        */
3645       if (ic->next && ic->next->op == GOTO
3646           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3647           && labelRange <= 5)
3648         {
3649           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3650           tlbl = IC_LABEL (ic->next);
3651           emitTlbl = 0;
3652         }
3653       else
3654         {
3655           tlbl = newiTempLabel (NULL);
3656           emitTlbl = 1;
3657         }
3658
3659       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3660       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3661           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3662           IS_AOP_PREG (IC_RESULT (ic)))
3663         emitcode ("cjne", "%s,#0xff,%05d$"
3664                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3665                   ,tlbl->key + 100);
3666       else
3667         {
3668           emitcode ("mov", "a,#0xff");
3669           emitcode ("cjne", "a,%s,%05d$"
3670                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3671                     ,tlbl->key + 100);
3672         }
3673       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3674       if (size > 2)
3675         {
3676           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3677               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3678               IS_AOP_PREG (IC_RESULT (ic)))
3679             emitcode ("cjne", "%s,#0xff,%05d$"
3680                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3681                       ,tlbl->key + 100);
3682           else
3683             {
3684               emitcode ("cjne", "a,%s,%05d$"
3685                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3686                         ,tlbl->key + 100);
3687             }
3688           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3689         }
3690       if (size > 3)
3691         {
3692           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3693               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3694               IS_AOP_PREG (IC_RESULT (ic)))
3695             emitcode ("cjne", "%s,#0xff,%05d$"
3696                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3697                       ,tlbl->key + 100);
3698           else
3699             {
3700               emitcode ("cjne", "a,%s,%05d$"
3701                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3702                         ,tlbl->key + 100);
3703             }
3704           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3705         }
3706       if (emitTlbl)
3707         {
3708           emitcode ("", "%05d$:", tlbl->key + 100);
3709         }
3710       return TRUE;
3711     }
3712
3713   /* if the sizes are greater than 1 then we cannot */
3714   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3715       AOP_SIZE (IC_LEFT (ic)) > 1)
3716     return FALSE;
3717
3718   /* we can if the aops of the left & result match or
3719      if they are in registers and the registers are the
3720      same */
3721   if (
3722        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3723        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3724        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3725     {
3726
3727       _startLazyDPSEvaluation ();
3728       while (icount--)
3729         {
3730           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3731         }
3732       _endLazyDPSEvaluation ();
3733
3734       return TRUE;
3735     }
3736
3737   return FALSE;
3738 }
3739
3740 /*-----------------------------------------------------------------*/
3741 /* addSign - complete with sign                                    */
3742 /*-----------------------------------------------------------------*/
3743 static void
3744 addSign (operand * result, int offset, int sign)
3745 {
3746   int size = (getDataSize (result) - offset);
3747   if (size > 0)
3748     {
3749       _startLazyDPSEvaluation();
3750       if (sign)
3751         {
3752           emitcode ("rlc", "a");
3753           emitcode ("subb", "a,acc");
3754           while (size--)
3755           {
3756             aopPut (AOP (result), "a", offset++);
3757           }
3758         }
3759       else
3760       {
3761         while (size--)
3762         {
3763           aopPut (AOP (result), zero, offset++);
3764         }
3765       }
3766       _endLazyDPSEvaluation();
3767     }
3768 }
3769
3770 /*-----------------------------------------------------------------*/
3771 /* genMinusBits - generates code for subtraction  of two bits      */
3772 /*-----------------------------------------------------------------*/
3773 static void
3774 genMinusBits (iCode * ic)
3775 {
3776   symbol *lbl = newiTempLabel (NULL);
3777
3778   D (emitcode (";", "genMinusBits "););
3779
3780   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3781     {
3782       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3783       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3784       emitcode ("cpl", "c");
3785       emitcode ("", "%05d$:", (lbl->key + 100));
3786       outBitC (IC_RESULT (ic));
3787     }
3788   else
3789     {
3790       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3791       emitcode ("subb", "a,acc");
3792       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3793       emitcode ("inc", "a");
3794       emitcode ("", "%05d$:", (lbl->key + 100));
3795       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3796       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3797     }
3798 }
3799
3800 /*-----------------------------------------------------------------*/
3801 /* genMinus - generates code for subtraction                       */
3802 /*-----------------------------------------------------------------*/
3803 static void
3804 genMinus (iCode * ic)
3805 {
3806   int size, offset = 0;
3807   int rSize;
3808   unsigned long lit = 0L;
3809   bool pushResult = FALSE;
3810
3811   D (emitcode (";", "genMinus "););
3812
3813   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3814   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3815   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3816       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3817     {
3818       pushResult = TRUE;
3819     }
3820   else
3821     {
3822       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3823
3824       /* special cases :- */
3825       /* if both left & right are in bit space */
3826       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3827           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3828         {
3829           genMinusBits (ic);
3830           goto release;
3831         }
3832
3833       /* if I can do an decrement instead
3834          of subtract then GOOD for ME */
3835       if (genMinusDec (ic) == TRUE)
3836         goto release;
3837
3838     }
3839
3840   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3841
3842   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3843     {
3844       CLRC;
3845     }
3846   else
3847     {
3848       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3849       lit = -(long) lit;
3850     }
3851
3852
3853   /* if literal, add a,#-lit, else normal subb */
3854   _startLazyDPSEvaluation ();
3855   while (size--)
3856     {
3857       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3858       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3859         emitcode ("subb", "a,%s",
3860                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3861       else
3862         {
3863           /* first add without previous c */
3864           if (!offset) {
3865             if (!size && lit==-1) {
3866               emitcode ("dec", "a");
3867             } else {
3868               emitcode ("add", "a,#0x%02x",
3869                         (unsigned int) (lit & 0x0FFL));
3870             }
3871           } else {
3872             emitcode ("addc", "a,#0x%02x",
3873                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3874           }
3875         }
3876
3877       if (pushResult)
3878         {
3879           emitcode ("push", "acc");
3880         }
3881       else
3882         {
3883           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3884         }
3885       offset++;
3886     }
3887   _endLazyDPSEvaluation ();
3888
3889   if (pushResult)
3890     {
3891       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3892
3893       size = getDataSize (IC_LEFT (ic));
3894       rSize = getDataSize (IC_RESULT (ic));
3895
3896       ADJUST_PUSHED_RESULT(size, rSize);
3897
3898       _startLazyDPSEvaluation ();
3899       while (size--)
3900         {
3901           emitcode ("pop", "acc");
3902           aopPut (AOP (IC_RESULT (ic)), "a", size);
3903         }
3904       _endLazyDPSEvaluation ();
3905     }
3906
3907   adjustArithmeticResult (ic);
3908
3909 release:
3910   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3911   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3912   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3913 }
3914
3915
3916 /*-----------------------------------------------------------------*/
3917 /* genMultbits :- multiplication of bits                           */
3918 /*-----------------------------------------------------------------*/
3919 static void
3920 genMultbits (operand * left,
3921              operand * right,
3922              operand * result,
3923              iCode   * ic)
3924 {
3925   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3926   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3927   aopOp(result, ic, TRUE, FALSE);
3928   outBitC (result);
3929 }
3930
3931
3932 /*-----------------------------------------------------------------*/
3933 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3934 /*-----------------------------------------------------------------*/
3935 static void
3936 genMultOneByte (operand * left,
3937                 operand * right,
3938                 operand * result,
3939                 iCode   * ic)
3940 {
3941   sym_link *opetype = operandType (result);
3942   symbol *lbl;
3943
3944
3945   /* (if two literals: the value is computed before) */
3946   /* if one literal, literal on the right */
3947   if (AOP_TYPE (left) == AOP_LIT)
3948     {
3949       operand *t = right;
3950       right = left;
3951       left = t;
3952       emitcode (";", "swapped left and right");
3953     }
3954
3955   if (SPEC_USIGN(opetype)
3956       // ignore the sign of left and right, what else can we do?
3957       || (SPEC_USIGN(operandType(left)) && 
3958           SPEC_USIGN(operandType(right)))) {
3959     // just an unsigned 8*8=8/16 multiply
3960     //emitcode (";","unsigned");
3961     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3962     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3963     emitcode ("mul", "ab");
3964    
3965     _G.accInUse++;
3966     aopOp(result, ic, TRUE, FALSE);
3967       
3968       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
3969       {
3970           // this should never happen
3971           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3972                    AOP_SIZE(result), __FILE__, lineno);
3973           exit (1);
3974       }      
3975       
3976     aopPut (AOP (result), "a", 0);
3977     _G.accInUse--;
3978     if (AOP_SIZE(result)==2) 
3979     {
3980       aopPut (AOP (result), "b", 1);
3981     }
3982     return;
3983   }
3984
3985   // we have to do a signed multiply
3986
3987   emitcode (";", "signed");
3988   emitcode ("clr", "F0"); // reset sign flag
3989   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3990
3991   lbl=newiTempLabel(NULL);
3992   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
3993   // left side is negative, 8-bit two's complement, this fails for -128
3994   emitcode ("setb", "F0"); // set sign flag
3995   emitcode ("cpl", "a");
3996   emitcode ("inc", "a");
3997
3998   emitcode ("", "%05d$:", lbl->key+100);
3999
4000   /* if literal */
4001   if (AOP_TYPE(right)==AOP_LIT) {
4002     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4003     /* AND literal negative */
4004     if ((int) val < 0) {
4005       emitcode ("cpl", "F0"); // complement sign flag
4006       emitcode ("mov", "b,#0x%02x", -val);
4007     } else {
4008       emitcode ("mov", "b,#0x%02x", val);
4009     }
4010   } else {
4011     lbl=newiTempLabel(NULL);
4012     emitcode ("mov", "b,a");
4013     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4014     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4015     // right side is negative, 8-bit two's complement
4016     emitcode ("cpl", "F0"); // complement sign flag
4017     emitcode ("cpl", "a");
4018     emitcode ("inc", "a");
4019     emitcode ("", "%05d$:", lbl->key+100);
4020   }
4021   emitcode ("mul", "ab");
4022     
4023   _G.accInUse++;
4024   aopOp(result, ic, TRUE, FALSE);
4025     
4026   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4027   {
4028     // this should never happen
4029       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4030                AOP_SIZE(result), __FILE__, lineno);
4031       exit (1);
4032   }    
4033     
4034   lbl=newiTempLabel(NULL);
4035   emitcode ("jnb", "F0,%05d$", lbl->key+100);
4036   // only ONE op was negative, we have to do a 8/16-bit two's complement
4037   emitcode ("cpl", "a"); // lsb
4038   if (AOP_SIZE(result)==1) {
4039     emitcode ("inc", "a");
4040   } else {
4041     emitcode ("add", "a,#1");
4042     emitcode ("xch", "a,b");
4043     emitcode ("cpl", "a"); // msb
4044     emitcode ("addc", "a,#0");
4045     emitcode ("xch", "a,b");
4046   }
4047
4048   emitcode ("", "%05d$:", lbl->key+100);
4049   aopPut (AOP (result), "a", 0);
4050   _G.accInUse--;
4051   if (AOP_SIZE(result)==2) {
4052     aopPut (AOP (result), "b", 1);
4053   }
4054 }
4055
4056 /*-----------------------------------------------------------------*/
4057 /* genMult - generates code for multiplication                     */
4058 /*-----------------------------------------------------------------*/
4059 static void
4060 genMult (iCode * ic)
4061 {
4062   operand *left = IC_LEFT (ic);
4063   operand *right = IC_RIGHT (ic);
4064   operand *result = IC_RESULT (ic);
4065
4066   D (emitcode (";", "genMult "););
4067
4068   /* assign the amsops */
4069   AOP_OP_2 (ic);
4070
4071   /* special cases first */
4072   /* both are bits */
4073   if (AOP_TYPE (left) == AOP_CRY &&
4074       AOP_TYPE (right) == AOP_CRY)
4075     {
4076       genMultbits (left, right, result, ic);
4077       goto release;
4078     }
4079
4080   /* if both are of size == 1 */
4081   if (AOP_SIZE (left) == 1 &&
4082       AOP_SIZE (right) == 1)
4083     {
4084       genMultOneByte (left, right, result, ic);
4085       goto release;
4086     }
4087
4088   /* should have been converted to function call */
4089   assert (1);
4090
4091 release:
4092   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4093   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4094   freeAsmop (result, NULL, ic, TRUE);
4095 }
4096
4097 /*-----------------------------------------------------------------*/
4098 /* genDivbits :- division of bits                                  */
4099 /*-----------------------------------------------------------------*/
4100 static void
4101 genDivbits (operand * left,
4102             operand * right,
4103             operand * result,
4104             iCode   * ic)
4105 {
4106
4107   char *l;
4108
4109   /* the result must be bit */
4110   LOAD_AB_FOR_DIV (left, right, l);
4111   emitcode ("div", "ab");
4112   emitcode ("rrc", "a");
4113   aopOp(result, ic, TRUE, FALSE);
4114     
4115   aopPut (AOP (result), "c", 0);
4116 }
4117
4118 /*-----------------------------------------------------------------*/
4119 /* genDivOneByte : 8 bit division                                  */
4120 /*-----------------------------------------------------------------*/
4121 static void
4122 genDivOneByte (operand * left,
4123                operand * right,
4124                operand * result,
4125                iCode   * ic)
4126 {
4127   sym_link *opetype = operandType (result);
4128   char *l;
4129   symbol *lbl;
4130   int size, offset;
4131
4132   offset = 1;
4133   /* signed or unsigned */
4134   if (SPEC_USIGN (opetype))
4135     {
4136         /* unsigned is easy */
4137         LOAD_AB_FOR_DIV (left, right, l);
4138         emitcode ("div", "ab");
4139
4140         _G.accInUse++;
4141         aopOp(result, ic, TRUE, FALSE);
4142         aopPut (AOP (result), "a", 0);
4143         _G.accInUse--;
4144
4145         size = AOP_SIZE (result) - 1;
4146         
4147         while (size--)
4148         {
4149             aopPut (AOP (result), zero, offset++);
4150         }
4151       return;
4152     }
4153
4154   /* signed is a little bit more difficult */
4155
4156   /* save the signs of the operands */
4157   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4158   MOVA (l);
4159   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4160   emitcode ("push", "acc");     /* save it on the stack */
4161
4162   /* now sign adjust for both left & right */
4163   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4164   MOVA (l);
4165   lbl = newiTempLabel (NULL);
4166   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4167   emitcode ("cpl", "a");
4168   emitcode ("inc", "a");
4169   emitcode ("", "%05d$:", (lbl->key + 100));
4170   emitcode ("mov", "b,a");
4171
4172   /* sign adjust left side */
4173   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4174   MOVA (l);
4175
4176   lbl = newiTempLabel (NULL);
4177   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4178   emitcode ("cpl", "a");
4179   emitcode ("inc", "a");
4180   emitcode ("", "%05d$:", (lbl->key + 100));
4181
4182   /* now the division */
4183   emitcode ("nop", "; workaround for DS80C390 div bug.");
4184   emitcode ("div", "ab");
4185   /* we are interested in the lower order
4186      only */
4187   emitcode ("mov", "b,a");
4188   lbl = newiTempLabel (NULL);
4189   emitcode ("pop", "acc");
4190   /* if there was an over flow we don't
4191      adjust the sign of the result */
4192   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4193   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4194   CLRC;
4195   emitcode ("clr", "a");
4196   emitcode ("subb", "a,b");
4197   emitcode ("mov", "b,a");
4198   emitcode ("", "%05d$:", (lbl->key + 100));
4199
4200   /* now we are done */
4201     _G.accInUse++;
4202     aopOp(result, ic, TRUE, FALSE);
4203     
4204     aopPut (AOP (result), "b", 0);
4205     
4206     size = AOP_SIZE (result) - 1;
4207     
4208     if (size > 0)
4209     {
4210       emitcode ("mov", "c,b.7");
4211       emitcode ("subb", "a,acc");
4212     }
4213     while (size--)
4214     {
4215         aopPut (AOP (result), "a", offset++);
4216     }
4217     _G.accInUse--;
4218
4219 }
4220
4221 /*-----------------------------------------------------------------*/
4222 /* genDiv - generates code for division                            */
4223 /*-----------------------------------------------------------------*/
4224 static void
4225 genDiv (iCode * ic)
4226 {
4227   operand *left = IC_LEFT (ic);
4228   operand *right = IC_RIGHT (ic);
4229   operand *result = IC_RESULT (ic);
4230
4231   D (emitcode (";", "genDiv "););
4232
4233   /* assign the amsops */
4234   AOP_OP_2 (ic);
4235
4236   /* special cases first */
4237   /* both are bits */
4238   if (AOP_TYPE (left) == AOP_CRY &&
4239       AOP_TYPE (right) == AOP_CRY)
4240     {
4241       genDivbits (left, right, result, ic);
4242       goto release;
4243     }
4244
4245   /* if both are of size == 1 */
4246   if (AOP_SIZE (left) == 1 &&
4247       AOP_SIZE (right) == 1)
4248     {
4249       genDivOneByte (left, right, result, ic);
4250       goto release;
4251     }
4252
4253   /* should have been converted to function call */
4254   assert (1);
4255 release:
4256   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4257   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4258   freeAsmop (result, NULL, ic, TRUE);
4259 }
4260
4261 /*-----------------------------------------------------------------*/
4262 /* genModbits :- modulus of bits                                   */
4263 /*-----------------------------------------------------------------*/
4264 static void
4265 genModbits (operand * left,
4266             operand * right,
4267             operand * result)
4268 {
4269
4270   char *l;
4271
4272   /* the result must be bit */
4273   LOAD_AB_FOR_DIV (left, right, l);
4274   emitcode ("div", "ab");
4275   emitcode ("mov", "a,b");
4276   emitcode ("rrc", "a");
4277   aopPut (AOP (result), "c", 0);
4278 }
4279
4280 /*-----------------------------------------------------------------*/
4281 /* genModOneByte : 8 bit modulus                                   */
4282 /*-----------------------------------------------------------------*/
4283 static void
4284 genModOneByte (operand * left,
4285                operand * right,
4286                operand * result)
4287 {
4288   sym_link *opetype = operandType (result);
4289   char *l;
4290   symbol *lbl;
4291
4292   /* signed or unsigned */
4293   if (SPEC_USIGN (opetype))
4294     {
4295       /* unsigned is easy */
4296       LOAD_AB_FOR_DIV (left, right, l);
4297       emitcode ("div", "ab");
4298       aopPut (AOP (result), "b", 0);
4299       return;
4300     }
4301
4302   /* signed is a little bit more difficult */
4303
4304   /* save the signs of the operands */
4305   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4306   MOVA (l);
4307
4308   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4309   emitcode ("push", "acc");     /* save it on the stack */
4310
4311   /* now sign adjust for both left & right */
4312   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4313   MOVA (l);
4314
4315   lbl = newiTempLabel (NULL);
4316   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4317   emitcode ("cpl", "a");
4318   emitcode ("inc", "a");
4319   emitcode ("", "%05d$:", (lbl->key + 100));
4320   emitcode ("mov", "b,a");
4321
4322   /* sign adjust left side */
4323   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4324   MOVA (l);
4325
4326   lbl = newiTempLabel (NULL);
4327   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4328   emitcode ("cpl", "a");
4329   emitcode ("inc", "a");
4330   emitcode ("", "%05d$:", (lbl->key + 100));
4331
4332   /* now the multiplication */
4333   emitcode ("nop", "; workaround for DS80C390 div bug.");
4334   emitcode ("div", "ab");
4335   /* we are interested in the lower order
4336      only */
4337   lbl = newiTempLabel (NULL);
4338   emitcode ("pop", "acc");
4339   /* if there was an over flow we don't
4340      adjust the sign of the result */
4341   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4342   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4343   CLRC;
4344   emitcode ("clr", "a");
4345   emitcode ("subb", "a,b");
4346   emitcode ("mov", "b,a");
4347   emitcode ("", "%05d$:", (lbl->key + 100));
4348
4349   /* now we are done */
4350   aopPut (AOP (result), "b", 0);
4351
4352 }
4353
4354 /*-----------------------------------------------------------------*/
4355 /* genMod - generates code for division                            */
4356 /*-----------------------------------------------------------------*/
4357 static void
4358 genMod (iCode * ic)
4359 {
4360   operand *left = IC_LEFT (ic);
4361   operand *right = IC_RIGHT (ic);
4362   operand *result = IC_RESULT (ic);
4363
4364   D (emitcode (";", "genMod ");
4365     );
4366
4367   /* assign the amsops */
4368   AOP_OP_3 (ic);
4369
4370   /* special cases first */
4371   /* both are bits */
4372   if (AOP_TYPE (left) == AOP_CRY &&
4373       AOP_TYPE (right) == AOP_CRY)
4374     {
4375       genModbits (left, right, result);
4376       goto release;
4377     }
4378
4379   /* if both are of size == 1 */
4380   if (AOP_SIZE (left) == 1 &&
4381       AOP_SIZE (right) == 1)
4382     {
4383       genModOneByte (left, right, result);
4384       goto release;
4385     }
4386
4387   /* should have been converted to function call */
4388   assert (1);
4389
4390 release:
4391   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4392   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4393   freeAsmop (result, NULL, ic, TRUE);
4394 }
4395
4396 /*-----------------------------------------------------------------*/
4397 /* genIfxJump :- will create a jump depending on the ifx           */
4398 /*-----------------------------------------------------------------*/
4399 static void
4400 genIfxJump (iCode * ic, char *jval)
4401 {
4402   symbol *jlbl;
4403   symbol *tlbl = newiTempLabel (NULL);
4404   char *inst;
4405
4406   D (emitcode (";", "genIfxJump ");
4407     );
4408
4409   /* if true label then we jump if condition
4410      supplied is true */
4411   if (IC_TRUE (ic))
4412     {
4413       jlbl = IC_TRUE (ic);
4414       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4415                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4416     }
4417   else
4418     {
4419       /* false label is present */
4420       jlbl = IC_FALSE (ic);
4421       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4422                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4423     }
4424   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4425     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4426   else
4427     emitcode (inst, "%05d$", tlbl->key + 100);
4428   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4429   emitcode ("", "%05d$:", tlbl->key + 100);
4430
4431   /* mark the icode as generated */
4432   ic->generated = 1;
4433 }
4434
4435 /*-----------------------------------------------------------------*/
4436 /* genCmp :- greater or less than comparison                       */
4437 /*-----------------------------------------------------------------*/
4438 static void
4439 genCmp (operand * left, operand * right,
4440         iCode * ic, iCode * ifx, int sign)
4441 {
4442   int size, offset = 0;
4443   unsigned long lit = 0L;
4444   operand *result;
4445
4446   D (emitcode (";", "genCmp");
4447     );
4448
4449   result = IC_RESULT (ic);
4450
4451   /* if left & right are bit variables */
4452   if (AOP_TYPE (left) == AOP_CRY &&
4453       AOP_TYPE (right) == AOP_CRY)
4454     {
4455       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4456       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4457     }
4458   else
4459     {
4460       /* subtract right from left if at the
4461          end the carry flag is set then we know that
4462          left is greater than right */
4463       size = max (AOP_SIZE (left), AOP_SIZE (right));
4464
4465       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4466       if ((size == 1) && !sign &&
4467           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4468         {
4469           symbol *lbl = newiTempLabel (NULL);
4470           emitcode ("cjne", "%s,%s,%05d$",
4471                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4472                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4473                     lbl->key + 100);
4474           emitcode ("", "%05d$:", lbl->key + 100);
4475         }
4476       else
4477         {
4478           if (AOP_TYPE (right) == AOP_LIT)
4479             {
4480               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4481               /* optimize if(x < 0) or if(x >= 0) */
4482               if (lit == 0L)
4483                 {
4484                   if (!sign)
4485                     {
4486                       CLRC;
4487                     }
4488                   else
4489                     {
4490                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4491
4492                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4493                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4494
4495                       aopOp (result, ic, FALSE, FALSE);
4496
4497                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4498                         {
4499                           freeAsmop (result, NULL, ic, TRUE);
4500                           genIfxJump (ifx, "acc.7");
4501                           return;
4502                         }
4503                       else
4504                         {
4505                           emitcode ("rlc", "a");
4506                         }
4507                       goto release_freedLR;
4508                     }
4509                   goto release;
4510                 }
4511             }
4512           CLRC;
4513           while (size--)
4514             {
4515               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4516               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4517               emitcode (";", "genCmp #2");
4518               if (sign && (size == 0))
4519                 {
4520                   emitcode (";", "genCmp #3");
4521                   emitcode ("xrl", "a,#0x80");
4522                   if (AOP_TYPE (right) == AOP_LIT)
4523                     {
4524                       unsigned long lit = (unsigned long)
4525                       floatFromVal (AOP (right)->aopu.aop_lit);
4526                       emitcode (";", "genCmp #3.1");
4527                       emitcode ("subb", "a,#0x%02x",
4528                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4529                     }
4530                   else
4531                     {
4532                       emitcode (";", "genCmp #3.2");
4533                       if (AOP_NEEDSACC (right))
4534                         {
4535                           emitcode ("push", "acc");
4536                         }
4537                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4538                                                        FALSE, FALSE, FALSE));
4539                       emitcode ("xrl", "b,#0x80");
4540                       if (AOP_NEEDSACC (right))
4541                         {
4542                           emitcode ("pop", "acc");
4543                         }
4544                       emitcode ("subb", "a,b");
4545                     }
4546                 }
4547               else
4548                 {
4549                   const char *s;
4550
4551                   emitcode (";", "genCmp #4");
4552                   if (AOP_NEEDSACC (right))
4553                     {
4554                       /* Yuck!! */
4555                       emitcode (";", "genCmp #4.1");
4556                       emitcode ("xch", "a, b");
4557                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4558                       emitcode ("xch", "a, b");
4559                       s = "b";
4560                     }
4561                   else
4562                     {
4563                       emitcode (";", "genCmp #4.2");
4564                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4565                     }
4566
4567                   emitcode ("subb", "a,%s", s);
4568                 }
4569             }
4570         }
4571     }
4572
4573 release:
4574 /* Don't need the left & right operands any more; do need the result. */
4575   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4576   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4577
4578   aopOp (result, ic, FALSE, FALSE);
4579
4580 release_freedLR:
4581
4582   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4583     {
4584       outBitC (result);
4585     }
4586   else
4587     {
4588       /* if the result is used in the next
4589          ifx conditional branch then generate
4590          code a little differently */
4591       if (ifx)
4592         {
4593           genIfxJump (ifx, "c");
4594         }
4595       else
4596         {
4597           outBitC (result);
4598         }
4599       /* leave the result in acc */
4600     }
4601   freeAsmop (result, NULL, ic, TRUE);
4602 }
4603
4604 /*-----------------------------------------------------------------*/
4605 /* genCmpGt :- greater than comparison                             */
4606 /*-----------------------------------------------------------------*/
4607 static void
4608 genCmpGt (iCode * ic, iCode * ifx)
4609 {
4610   operand *left, *right;
4611   sym_link *letype, *retype;
4612   int sign;
4613
4614   D (emitcode (";", "genCmpGt ");
4615     );
4616
4617   left = IC_LEFT (ic);
4618   right = IC_RIGHT (ic);
4619
4620   letype = getSpec (operandType (left));
4621   retype = getSpec (operandType (right));
4622   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4623
4624   /* assign the left & right amsops */
4625   AOP_OP_2 (ic);
4626
4627   genCmp (right, left, ic, ifx, sign);
4628 }
4629
4630 /*-----------------------------------------------------------------*/
4631 /* genCmpLt - less than comparisons                                */
4632 /*-----------------------------------------------------------------*/
4633 static void
4634 genCmpLt (iCode * ic, iCode * ifx)
4635 {
4636   operand *left, *right;
4637   sym_link *letype, *retype;
4638   int sign;
4639
4640   D (emitcode (";", "genCmpLt "););
4641
4642   left = IC_LEFT (ic);
4643   right = IC_RIGHT (ic);
4644
4645   letype = getSpec (operandType (left));
4646   retype = getSpec (operandType (right));
4647   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4648
4649   /* assign the left & right amsops */
4650   AOP_OP_2 (ic);
4651
4652   genCmp (left, right, ic, ifx, sign);
4653 }
4654
4655 /*-----------------------------------------------------------------*/
4656 /* gencjneshort - compare and jump if not equal                    */
4657 /*-----------------------------------------------------------------*/
4658 static void
4659 gencjneshort (operand * left, operand * right, symbol * lbl)
4660 {
4661   int size = max (AOP_SIZE (left), AOP_SIZE (right));
4662   int offset = 0;
4663   unsigned long lit = 0L;
4664
4665   D (emitcode (";", "gencjneshort");
4666     );
4667
4668   /* if the left side is a literal or
4669      if the right is in a pointer register and left
4670      is not */
4671   if ((AOP_TYPE (left) == AOP_LIT) ||
4672       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4673     {
4674       operand *t = right;
4675       right = left;
4676       left = t;
4677     }
4678
4679   if (AOP_TYPE (right) == AOP_LIT)
4680     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4681
4682   if (opIsGptr (left) || opIsGptr (right))
4683     {
4684       /* We are comparing a generic pointer to something.
4685        * Exclude the generic type byte from the comparison.
4686        */
4687       size--;
4688       D (emitcode (";", "cjneshort: generic ptr special case.");
4689         )
4690     }
4691
4692
4693   /* if the right side is a literal then anything goes */
4694   if (AOP_TYPE (right) == AOP_LIT &&
4695       AOP_TYPE (left) != AOP_DIR)
4696     {
4697       while (size--)
4698         {
4699           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4700           MOVA (l);
4701           emitcode ("cjne", "a,%s,%05d$",
4702                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4703                     lbl->key + 100);
4704           offset++;
4705         }
4706     }
4707
4708   /* if the right side is in a register or in direct space or
4709      if the left is a pointer register & right is not */
4710   else if (AOP_TYPE (right) == AOP_REG ||
4711            AOP_TYPE (right) == AOP_DIR ||
4712            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4713            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4714     {
4715       while (size--)
4716         {
4717           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4718           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4719               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4720             emitcode ("jnz", "%05d$", lbl->key + 100);
4721           else
4722             emitcode ("cjne", "a,%s,%05d$",
4723                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4724                       lbl->key + 100);
4725           offset++;
4726         }
4727     }
4728   else
4729     {
4730       /* right is a pointer reg need both a & b */
4731       while (size--)
4732         {
4733           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4734           if (strcmp (l, "b"))
4735             emitcode ("mov", "b,%s", l);
4736           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4737           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4738           offset++;
4739         }
4740     }
4741 }
4742
4743 /*-----------------------------------------------------------------*/
4744 /* gencjne - compare and jump if not equal                         */
4745 /*-----------------------------------------------------------------*/
4746 static void
4747 gencjne (operand * left, operand * right, symbol * lbl)
4748 {
4749   symbol *tlbl = newiTempLabel (NULL);
4750
4751   D (emitcode (";", "gencjne");
4752     );
4753
4754   gencjneshort (left, right, lbl);
4755
4756   emitcode ("mov", "a,%s", one);
4757   emitcode ("sjmp", "%05d$", tlbl->key + 100);
4758   emitcode ("", "%05d$:", lbl->key + 100);
4759   emitcode ("clr", "a");
4760   emitcode ("", "%05d$:", tlbl->key + 100);
4761 }
4762
4763 /*-----------------------------------------------------------------*/
4764 /* genCmpEq - generates code for equal to                          */
4765 /*-----------------------------------------------------------------*/
4766 static void
4767 genCmpEq (iCode * ic, iCode * ifx)
4768 {
4769   operand *left, *right, *result;
4770
4771   D (emitcode (";", "genCmpEq ");
4772     );
4773
4774   AOP_OP_2 (ic);
4775   AOP_SET_LOCALS (ic);
4776
4777   /* if literal, literal on the right or
4778      if the right is in a pointer register and left
4779      is not */
4780   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4781       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4782     {
4783       operand *t = IC_RIGHT (ic);
4784       IC_RIGHT (ic) = IC_LEFT (ic);
4785       IC_LEFT (ic) = t;
4786     }
4787
4788   if (ifx &&                    /* !AOP_SIZE(result) */
4789       OP_SYMBOL (result) &&
4790       OP_SYMBOL (result)->regType == REG_CND)
4791     {
4792       symbol *tlbl;
4793       /* if they are both bit variables */
4794       if (AOP_TYPE (left) == AOP_CRY &&
4795           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4796         {
4797           if (AOP_TYPE (right) == AOP_LIT)
4798             {
4799               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4800               if (lit == 0L)
4801                 {
4802                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4803                   emitcode ("cpl", "c");
4804                 }
4805               else if (lit == 1L)
4806                 {
4807                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4808                 }
4809               else
4810                 {
4811                   emitcode ("clr", "c");
4812                 }
4813               /* AOP_TYPE(right) == AOP_CRY */
4814             }
4815           else
4816             {
4817               symbol *lbl = newiTempLabel (NULL);
4818               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4819               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4820               emitcode ("cpl", "c");
4821               emitcode ("", "%05d$:", (lbl->key + 100));
4822             }
4823           /* if true label then we jump if condition
4824              supplied is true */
4825           tlbl = newiTempLabel (NULL);
4826           if (IC_TRUE (ifx))
4827             {
4828               emitcode ("jnc", "%05d$", tlbl->key + 100);
4829               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4830             }
4831           else
4832             {
4833               emitcode ("jc", "%05d$", tlbl->key + 100);
4834               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4835             }
4836           emitcode ("", "%05d$:", tlbl->key + 100);
4837         }
4838       else
4839         {
4840           tlbl = newiTempLabel (NULL);
4841           gencjneshort (left, right, tlbl);
4842           if (IC_TRUE (ifx))
4843             {
4844               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4845               emitcode ("", "%05d$:", tlbl->key + 100);
4846             }
4847           else
4848             {
4849               symbol *lbl = newiTempLabel (NULL);
4850               emitcode ("sjmp", "%05d$", lbl->key + 100);
4851               emitcode ("", "%05d$:", tlbl->key + 100);
4852               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4853               emitcode ("", "%05d$:", lbl->key + 100);
4854             }
4855         }
4856       /* mark the icode as generated */
4857       ifx->generated = 1;
4858
4859       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4860       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4861       return;
4862     }
4863
4864   /* if they are both bit variables */
4865   if (AOP_TYPE (left) == AOP_CRY &&
4866       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4867     {
4868       if (AOP_TYPE (right) == AOP_LIT)
4869         {
4870           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4871           if (lit == 0L)
4872             {
4873               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4874               emitcode ("cpl", "c");
4875             }
4876           else if (lit == 1L)
4877             {
4878               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4879             }
4880           else
4881             {
4882               emitcode ("clr", "c");
4883             }
4884           /* AOP_TYPE(right) == AOP_CRY */
4885         }
4886       else
4887         {
4888           symbol *lbl = newiTempLabel (NULL);
4889           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4890           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4891           emitcode ("cpl", "c");
4892           emitcode ("", "%05d$:", (lbl->key + 100));
4893         }
4894
4895       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4896       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4897
4898       aopOp (result, ic, TRUE, FALSE);
4899
4900       /* c = 1 if egal */
4901       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4902         {
4903           outBitC (result);
4904           goto release;
4905         }
4906       if (ifx)
4907         {
4908           genIfxJump (ifx, "c");
4909           goto release;
4910         }
4911       /* if the result is used in an arithmetic operation
4912          then put the result in place */
4913       outBitC (result);
4914     }
4915   else
4916     {
4917       gencjne (left, right, newiTempLabel (NULL));
4918
4919       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4920       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4921
4922       aopOp (result, ic, TRUE, FALSE);
4923
4924       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4925         {
4926           aopPut (AOP (result), "a", 0);
4927           goto release;
4928         }
4929       if (ifx)
4930         {
4931           genIfxJump (ifx, "a");
4932           goto release;
4933         }
4934       /* if the result is used in an arithmetic operation
4935          then put the result in place */
4936       if (AOP_TYPE (result) != AOP_CRY)
4937         outAcc (result);
4938       /* leave the result in acc */
4939     }
4940
4941 release:
4942   freeAsmop (result, NULL, ic, TRUE);
4943 }
4944
4945 /*-----------------------------------------------------------------*/
4946 /* ifxForOp - returns the icode containing the ifx for operand     */
4947 /*-----------------------------------------------------------------*/
4948 static iCode *
4949 ifxForOp (operand * op, iCode * ic)
4950 {
4951   /* if true symbol then needs to be assigned */
4952   if (IS_TRUE_SYMOP (op))
4953     return NULL;
4954
4955   /* if this has register type condition and
4956      the next instruction is ifx with the same operand
4957      and live to of the operand is upto the ifx only then */
4958   if (ic->next &&
4959       ic->next->op == IFX &&
4960       IC_COND (ic->next)->key == op->key &&
4961       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4962     return ic->next;
4963
4964   return NULL;
4965 }
4966 /*-----------------------------------------------------------------*/
4967 /* genAndOp - for && operation                                     */
4968 /*-----------------------------------------------------------------*/
4969 static void
4970 genAndOp (iCode * ic)
4971 {
4972   operand *left, *right, *result;
4973   symbol *tlbl;
4974
4975   D (emitcode (";", "genAndOp "););
4976
4977   /* note here that && operations that are in an
4978      if statement are taken away by backPatchLabels
4979      only those used in arthmetic operations remain */
4980   AOP_OP_2 (ic);
4981   AOP_SET_LOCALS (ic);
4982
4983   /* if both are bit variables */
4984   if (AOP_TYPE (left) == AOP_CRY &&
4985       AOP_TYPE (right) == AOP_CRY)
4986     {
4987       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4988       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4989       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4990       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4991   
4992       aopOp (result,ic,FALSE, FALSE);
4993       outBitC (result);
4994     }
4995   else
4996     {
4997       tlbl = newiTempLabel (NULL);
4998       toBoolean (left);
4999       emitcode ("jz", "%05d$", tlbl->key + 100);
5000       toBoolean (right);
5001       emitcode ("", "%05d$:", tlbl->key + 100);
5002       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5003       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5004   
5005       aopOp (result,ic,FALSE, FALSE);
5006       outBitAcc (result);
5007     }
5008     freeAsmop (result, NULL, ic, TRUE);
5009 }
5010
5011
5012 /*-----------------------------------------------------------------*/
5013 /* genOrOp - for || operation                                      */
5014 /*-----------------------------------------------------------------*/
5015 static void
5016 genOrOp (iCode * ic)
5017 {
5018   operand *left, *right, *result;
5019   symbol *tlbl;
5020
5021   D (emitcode (";", "genOrOp "););
5022
5023   /* note here that || operations that are in an
5024      if statement are taken away by backPatchLabels
5025      only those used in arthmetic operations remain */
5026   AOP_OP_2 (ic);
5027   AOP_SET_LOCALS (ic);
5028
5029   /* if both are bit variables */
5030   if (AOP_TYPE (left) == AOP_CRY &&
5031       AOP_TYPE (right) == AOP_CRY)
5032     {
5033       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5034       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5035       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5036       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5037   
5038       aopOp (result,ic,FALSE, FALSE);
5039       
5040       outBitC (result);
5041     }
5042   else
5043     {
5044       tlbl = newiTempLabel (NULL);
5045       toBoolean (left);
5046       emitcode ("jnz", "%05d$", tlbl->key + 100);
5047       toBoolean (right);
5048       emitcode ("", "%05d$:", tlbl->key + 100);
5049       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5050       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5051   
5052       aopOp (result,ic,FALSE, FALSE);
5053       
5054       outBitAcc (result);
5055     }
5056
5057   freeAsmop (result, NULL, ic, TRUE);
5058 }
5059
5060 /*-----------------------------------------------------------------*/
5061 /* isLiteralBit - test if lit == 2^n                               */
5062 /*-----------------------------------------------------------------*/
5063 static int
5064 isLiteralBit (unsigned long lit)
5065 {
5066   unsigned long pw[32] =
5067   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5068    0x100L, 0x200L, 0x400L, 0x800L,
5069    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5070    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5071    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5072    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5073    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5074   int idx;
5075
5076   for (idx = 0; idx < 32; idx++)
5077     if (lit == pw[idx])
5078       return idx + 1;
5079   return 0;
5080 }
5081
5082 /*-----------------------------------------------------------------*/
5083 /* continueIfTrue -                                                */
5084 /*-----------------------------------------------------------------*/
5085 static void
5086 continueIfTrue (iCode * ic)
5087 {
5088   if (IC_TRUE (ic))
5089     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5090   ic->generated = 1;
5091 }
5092
5093 /*-----------------------------------------------------------------*/
5094 /* jmpIfTrue -                                                     */
5095 /*-----------------------------------------------------------------*/
5096 static void
5097 jumpIfTrue (iCode * ic)
5098 {
5099   if (!IC_TRUE (ic))
5100     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5101   ic->generated = 1;
5102 }
5103
5104 /*-----------------------------------------------------------------*/
5105 /* jmpTrueOrFalse -                                                */
5106 /*-----------------------------------------------------------------*/
5107 static void
5108 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5109 {
5110   // ugly but optimized by peephole
5111   if (IC_TRUE (ic))
5112     {
5113       symbol *nlbl = newiTempLabel (NULL);
5114       emitcode ("sjmp", "%05d$", nlbl->key + 100);
5115       emitcode ("", "%05d$:", tlbl->key + 100);
5116       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5117       emitcode ("", "%05d$:", nlbl->key + 100);
5118     }
5119   else
5120     {
5121       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5122       emitcode ("", "%05d$:", tlbl->key + 100);
5123     }
5124   ic->generated = 1;
5125 }
5126
5127 // Generate code to perform a bit-wise logic operation
5128 // on two operands in far space (assumed to already have been 
5129 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5130 // in far space. This requires pushing the result on the stack
5131 // then popping it into the result.
5132 static void
5133 genFarFarLogicOp(iCode *ic, char *logicOp)
5134 {
5135       int size, resultSize, compSize;
5136       int offset = 0;
5137       
5138       TR_AP("#5");
5139       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5140       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5141                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5142       
5143       _startLazyDPSEvaluation();
5144       for (size = compSize; (size--); offset++)
5145       {
5146           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5147           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5148           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5149           
5150           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5151           emitcode ("push", "acc");
5152       }
5153       _endLazyDPSEvaluation();
5154      
5155       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5156       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5157       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5158      
5159       resultSize = AOP_SIZE(IC_RESULT(ic));
5160
5161       ADJUST_PUSHED_RESULT(compSize, resultSize);
5162
5163       _startLazyDPSEvaluation();
5164       while (compSize--)
5165       {
5166           emitcode ("pop", "acc");
5167           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5168       }
5169       _endLazyDPSEvaluation();
5170       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5171 }
5172
5173
5174 /*-----------------------------------------------------------------*/
5175 /* genAnd  - code for and                                          */
5176 /*-----------------------------------------------------------------*/
5177 static void
5178 genAnd (iCode * ic, iCode * ifx)
5179 {
5180   operand *left, *right, *result;
5181   int size, offset = 0;
5182   unsigned long lit = 0L;
5183   int bytelit = 0;
5184   char buffer[10];
5185   bool pushResult;
5186
5187   D (emitcode (";", "genAnd "););
5188
5189   AOP_OP_3_NOFATAL (ic, pushResult);
5190   AOP_SET_LOCALS (ic);
5191
5192   if (pushResult)
5193   {
5194       genFarFarLogicOp(ic, "anl");
5195       return;
5196   }  
5197
5198 #ifdef DEBUG_TYPE
5199   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5200             AOP_TYPE (result),
5201             AOP_TYPE (left), AOP_TYPE (right));
5202   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5203             AOP_SIZE (result),
5204             AOP_SIZE (left), AOP_SIZE (right));
5205 #endif
5206
5207   /* if left is a literal & right is not then exchange them */
5208   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5209       AOP_NEEDSACC (left))
5210     {
5211       operand *tmp = right;
5212       right = left;
5213       left = tmp;
5214     }
5215
5216   /* if result = right then exchange them */
5217   if (sameRegs (AOP (result), AOP (right)))
5218     {
5219       operand *tmp = right;
5220       right = left;
5221       left = tmp;
5222     }
5223
5224   /* if right is bit then exchange them */
5225   if (AOP_TYPE (right) == AOP_CRY &&
5226       AOP_TYPE (left) != AOP_CRY)
5227     {
5228       operand *tmp = right;
5229       right = left;
5230       left = tmp;
5231     }
5232   if (AOP_TYPE (right) == AOP_LIT)
5233     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5234
5235   size = AOP_SIZE (result);
5236
5237   // if(bit & yy)
5238   // result = bit & yy;
5239   if (AOP_TYPE (left) == AOP_CRY)
5240     {
5241       // c = bit & literal;
5242       if (AOP_TYPE (right) == AOP_LIT)
5243         {
5244           if (lit & 1)
5245             {
5246               if (size && sameRegs (AOP (result), AOP (left)))
5247                 // no change
5248                 goto release;
5249               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5250             }
5251           else
5252             {
5253               // bit(result) = 0;
5254               if (size && (AOP_TYPE (result) == AOP_CRY))
5255                 {
5256                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5257                   goto release;
5258                 }
5259               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5260                 {
5261                   jumpIfTrue (ifx);
5262                   goto release;
5263                 }
5264               emitcode ("clr", "c");
5265             }
5266         }
5267       else
5268         {
5269           if (AOP_TYPE (right) == AOP_CRY)
5270             {
5271               // c = bit & bit;
5272               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5273               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5274             }
5275           else
5276             {
5277               // c = bit & val;
5278               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5279               // c = lsb
5280               emitcode ("rrc", "a");
5281               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5282             }
5283         }
5284       // bit = c
5285       // val = c
5286       if (size)
5287         outBitC (result);
5288       // if(bit & ...)
5289       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5290         genIfxJump (ifx, "c");
5291       goto release;
5292     }
5293
5294   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5295   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5296   if ((AOP_TYPE (right) == AOP_LIT) &&
5297       (AOP_TYPE (result) == AOP_CRY) &&
5298       (AOP_TYPE (left) != AOP_CRY))
5299     {
5300       int posbit = isLiteralBit (lit);
5301       /* left &  2^n */
5302       if (posbit)
5303         {
5304           posbit--;
5305           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5306           // bit = left & 2^n
5307           if (size)
5308             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5309           // if(left &  2^n)
5310           else
5311             {
5312               if (ifx)
5313                 {
5314                   sprintf (buffer, "acc.%d", posbit & 0x07);
5315                   genIfxJump (ifx, buffer);
5316                 }
5317               goto release;
5318             }
5319         }
5320       else
5321         {
5322           symbol *tlbl = newiTempLabel (NULL);
5323           int sizel = AOP_SIZE (left);
5324           if (size)
5325             emitcode ("setb", "c");
5326           while (sizel--)
5327             {
5328               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5329                 {
5330                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5331                   // byte ==  2^n ?
5332                   if ((posbit = isLiteralBit (bytelit)) != 0)
5333                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5334                   else
5335                     {
5336                       if (bytelit != 0x0FFL)
5337                         emitcode ("anl", "a,%s",
5338                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5339                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5340                     }
5341                 }
5342               offset++;
5343             }
5344           // bit = left & literal
5345           if (size)
5346             {
5347               emitcode ("clr", "c");
5348               emitcode ("", "%05d$:", tlbl->key + 100);
5349             }
5350           // if(left & literal)
5351           else
5352             {
5353               if (ifx)
5354                 jmpTrueOrFalse (ifx, tlbl);
5355               goto release;
5356             }
5357         }
5358       outBitC (result);
5359       goto release;
5360     }
5361
5362   /* if left is same as result */
5363   if (sameRegs (AOP (result), AOP (left)))
5364     {
5365       for (; size--; offset++)
5366         {
5367           if (AOP_TYPE (right) == AOP_LIT)
5368             {
5369               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5370                 continue;
5371               else if (bytelit == 0)
5372                 aopPut (AOP (result), zero, offset);
5373               else if (IS_AOP_PREG (result))
5374                 {
5375                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5376                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5377                   aopPut (AOP (result), "a", offset);
5378                 }
5379               else
5380                 emitcode ("anl", "%s,%s",
5381                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5382                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5383             }
5384           else
5385             {
5386               if (AOP_TYPE (left) == AOP_ACC)
5387                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5388               else
5389                 {
5390                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5391                   if (IS_AOP_PREG (result))
5392                     {
5393                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5394                       aopPut (AOP (result), "a", offset);
5395
5396                     }
5397                   else
5398                     emitcode ("anl", "%s,a",
5399                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5400                 }
5401             }
5402         }
5403     }
5404   else
5405     {
5406       // left & result in different registers
5407       if (AOP_TYPE (result) == AOP_CRY)
5408         {
5409           // result = bit
5410           // if(size), result in bit
5411           // if(!size && ifx), conditional oper: if(left & right)
5412           symbol *tlbl = newiTempLabel (NULL);
5413           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5414           if (size)
5415             emitcode ("setb", "c");
5416           while (sizer--)
5417             {
5418               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5419                 emitcode ("anl", "a,%s",
5420                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5421               } else {
5422                 if (AOP_TYPE(left)==AOP_ACC) {
5423                   emitcode("mov", "b,a");
5424                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5425                   emitcode("anl", "a,b");
5426                 }else {
5427                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5428                   emitcode ("anl", "a,%s",
5429                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5430                 }
5431               }
5432               emitcode ("jnz", "%05d$", tlbl->key + 100);
5433               offset++;
5434             }
5435           if (size)
5436             {
5437               CLRC;
5438               emitcode ("", "%05d$:", tlbl->key + 100);
5439               outBitC (result);
5440             }
5441           else if (ifx)
5442             jmpTrueOrFalse (ifx, tlbl);
5443         }
5444       else
5445         {
5446           for (; (size--); offset++)
5447             {
5448               // normal case
5449               // result = left & right
5450               if (AOP_TYPE (right) == AOP_LIT)
5451                 {
5452                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5453                     {
5454                       aopPut (AOP (result),
5455                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5456                               offset);
5457                       continue;
5458                     }
5459                   else if (bytelit == 0)
5460                     {
5461                       aopPut (AOP (result), zero, offset);
5462                       continue;
5463                     }
5464                   D (emitcode (";", "better literal AND.");
5465                     );
5466                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5467                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5468                                                     FALSE, FALSE, FALSE));
5469
5470                 }
5471               else
5472                 {
5473                   // faster than result <- left, anl result,right
5474                   // and better if result is SFR
5475                   if (AOP_TYPE (left) == AOP_ACC)
5476                     {
5477                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5478                                                        FALSE, FALSE, FALSE));
5479                     }
5480                   else
5481                     {
5482                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5483                       emitcode ("anl", "a,%s",
5484                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5485                     }
5486                 }
5487               aopPut (AOP (result), "a", offset);
5488             }
5489         }
5490     }
5491
5492 release:
5493   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5494   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5495   freeAsmop (result, NULL, ic, TRUE);
5496 }
5497
5498
5499 /*-----------------------------------------------------------------*/
5500 /* genOr  - code for or                                            */
5501 /*-----------------------------------------------------------------*/
5502 static void
5503 genOr (iCode * ic, iCode * ifx)
5504 {
5505   operand *left, *right, *result;
5506   int size, offset = 0;
5507   unsigned long lit = 0L;
5508   bool     pushResult;
5509
5510   D (emitcode (";", "genOr "););
5511
5512   AOP_OP_3_NOFATAL (ic, pushResult);
5513   AOP_SET_LOCALS (ic);
5514
5515   if (pushResult)
5516   {
5517       genFarFarLogicOp(ic, "orl");
5518       return;
5519   }
5520
5521
5522 #ifdef DEBUG_TYPE
5523   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5524             AOP_TYPE (result),
5525             AOP_TYPE (left), AOP_TYPE (right));
5526   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5527             AOP_SIZE (result),
5528             AOP_SIZE (left), AOP_SIZE (right));
5529 #endif
5530
5531   /* if left is a literal & right is not then exchange them */
5532   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5533       AOP_NEEDSACC (left))
5534     {
5535       operand *tmp = right;
5536       right = left;
5537       left = tmp;
5538     }
5539
5540   /* if result = right then exchange them */
5541   if (sameRegs (AOP (result), AOP (right)))
5542     {
5543       operand *tmp = right;
5544       right = left;
5545       left = tmp;
5546     }
5547
5548   /* if right is bit then exchange them */
5549   if (AOP_TYPE (right) == AOP_CRY &&
5550       AOP_TYPE (left) != AOP_CRY)
5551     {
5552       operand *tmp = right;
5553       right = left;
5554       left = tmp;
5555     }
5556   if (AOP_TYPE (right) == AOP_LIT)
5557     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5558
5559   size = AOP_SIZE (result);
5560
5561   // if(bit | yy)
5562   // xx = bit | yy;
5563   if (AOP_TYPE (left) == AOP_CRY)
5564     {
5565       if (AOP_TYPE (right) == AOP_LIT)
5566         {
5567           // c = bit & literal;
5568           if (lit)
5569             {
5570               // lit != 0 => result = 1
5571               if (AOP_TYPE (result) == AOP_CRY)
5572                 {
5573                   if (size)
5574                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5575                   else if (ifx)
5576                     continueIfTrue (ifx);
5577                   goto release;
5578                 }
5579               emitcode ("setb", "c");
5580             }
5581           else
5582             {
5583               // lit == 0 => result = left
5584               if (size && sameRegs (AOP (result), AOP (left)))
5585                 goto release;
5586               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5587             }
5588         }
5589       else
5590         {
5591           if (AOP_TYPE (right) == AOP_CRY)
5592             {
5593               // c = bit | bit;
5594               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5595               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5596             }
5597           else
5598             {
5599               // c = bit | val;
5600               symbol *tlbl = newiTempLabel (NULL);
5601               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5602                 emitcode ("setb", "c");
5603               emitcode ("jb", "%s,%05d$",
5604                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
5605               toBoolean (right);
5606               emitcode ("jnz", "%05d$", tlbl->key + 100);
5607               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5608                 {
5609                   jmpTrueOrFalse (ifx, tlbl);
5610                   goto release;
5611                 }
5612               else
5613                 {
5614                   CLRC;
5615                   emitcode ("", "%05d$:", tlbl->key + 100);
5616                 }
5617             }
5618         }
5619       // bit = c
5620       // val = c
5621       if (size)
5622         outBitC (result);
5623       // if(bit | ...)
5624       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5625         genIfxJump (ifx, "c");
5626       goto release;
5627     }
5628
5629   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5630   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5631   if ((AOP_TYPE (right) == AOP_LIT) &&
5632       (AOP_TYPE (result) == AOP_CRY) &&
5633       (AOP_TYPE (left) != AOP_CRY))
5634     {
5635       if (lit)
5636         {
5637           // result = 1
5638           if (size)
5639             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5640           else
5641             continueIfTrue (ifx);
5642           goto release;
5643         }
5644       else
5645         {
5646           // lit = 0, result = boolean(left)
5647           if (size)
5648             emitcode ("setb", "c");
5649           toBoolean (right);
5650           if (size)
5651             {
5652               symbol *tlbl = newiTempLabel (NULL);
5653               emitcode ("jnz", "%05d$", tlbl->key + 100);
5654               CLRC;
5655               emitcode ("", "%05d$:", tlbl->key + 100);
5656             }
5657           else
5658             {
5659               genIfxJump (ifx, "a");
5660               goto release;
5661             }
5662         }
5663       outBitC (result);
5664       goto release;
5665     }
5666
5667   /* if left is same as result */
5668   if (sameRegs (AOP (result), AOP (left)))
5669     {
5670       for (; size--; offset++)
5671         {
5672           if (AOP_TYPE (right) == AOP_LIT)
5673             {
5674               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5675                 {
5676                   continue;
5677                 }
5678               else
5679                 {
5680                   if (IS_AOP_PREG (left))
5681                     {
5682                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5683                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5684                       aopPut (AOP (result), "a", offset);
5685                     }
5686                   else
5687                     {
5688                       emitcode ("orl", "%s,%s",
5689                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5690                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5691                     }
5692                 }
5693             }
5694           else
5695             {
5696               if (AOP_TYPE (left) == AOP_ACC)
5697                 {
5698                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5699                 }
5700               else
5701                 {
5702                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5703                   if (IS_AOP_PREG (left))
5704                     {
5705                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5706                       aopPut (AOP (result), "a", offset);
5707                     }
5708                   else
5709                     {
5710                       emitcode ("orl", "%s,a",
5711                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5712                     }
5713                 }
5714             }
5715         }
5716     }
5717   else
5718     {
5719       // left & result in different registers
5720       if (AOP_TYPE (result) == AOP_CRY)
5721         {
5722           // result = bit
5723           // if(size), result in bit
5724           // if(!size && ifx), conditional oper: if(left | right)
5725           symbol *tlbl = newiTempLabel (NULL);
5726           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5727           if (size)
5728             emitcode ("setb", "c");
5729           while (sizer--)
5730             {
5731               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5732                 emitcode ("orl", "a,%s",
5733                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5734               } else {
5735                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5736                 emitcode ("orl", "a,%s",
5737                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5738               }
5739               emitcode ("jnz", "%05d$", tlbl->key + 100);
5740               offset++;
5741             }
5742           if (size)
5743             {
5744               CLRC;
5745               emitcode ("", "%05d$:", tlbl->key + 100);
5746               outBitC (result);
5747             }
5748           else if (ifx)
5749             jmpTrueOrFalse (ifx, tlbl);
5750         }
5751       else
5752         {
5753           for (; (size--); offset++)
5754             {
5755               // normal case
5756               // result = left & right
5757               if (AOP_TYPE (right) == AOP_LIT)
5758                 {
5759                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5760                     {
5761                       aopPut (AOP (result),
5762                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5763                               offset);
5764                       continue;
5765                     }
5766                   D (emitcode (";", "better literal OR.");
5767                     );
5768                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5769                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5770                                                     FALSE, FALSE, FALSE));
5771
5772                 }
5773               else
5774                 {
5775                   // faster than result <- left, anl result,right
5776                   // and better if result is SFR
5777                   if (AOP_TYPE (left) == AOP_ACC)
5778                     {
5779                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5780                                                        FALSE, FALSE, FALSE));
5781                     }
5782                   else
5783                     {
5784                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5785                       emitcode ("orl", "a,%s",
5786                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5787                     }
5788                 }
5789               aopPut (AOP (result), "a", offset);
5790             }
5791         }
5792     }
5793
5794 release:
5795   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5796   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5797   freeAsmop (result, NULL, ic, TRUE);
5798 }
5799
5800 /*-----------------------------------------------------------------*/
5801 /* genXor - code for xclusive or                                   */
5802 /*-----------------------------------------------------------------*/
5803 static void
5804 genXor (iCode * ic, iCode * ifx)
5805 {
5806   operand *left, *right, *result;
5807   int size, offset = 0;
5808   unsigned long lit = 0L;
5809   bool pushResult;
5810
5811   D (emitcode (";", "genXor "););
5812
5813   AOP_OP_3_NOFATAL (ic, pushResult);
5814   AOP_SET_LOCALS (ic);
5815
5816   if (pushResult)
5817   {
5818       genFarFarLogicOp(ic, "xrl");
5819       return;
5820   }  
5821
5822 #ifdef DEBUG_TYPE
5823   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5824             AOP_TYPE (result),
5825             AOP_TYPE (left), AOP_TYPE (right));
5826   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5827             AOP_SIZE (result),
5828             AOP_SIZE (left), AOP_SIZE (right));
5829 #endif
5830
5831   /* if left is a literal & right is not ||
5832      if left needs acc & right does not */
5833   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5834       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5835     {
5836       operand *tmp = right;
5837       right = left;
5838       left = tmp;
5839     }
5840
5841   /* if result = right then exchange them */
5842   if (sameRegs (AOP (result), AOP (right)))
5843     {
5844       operand *tmp = right;
5845       right = left;
5846       left = tmp;
5847     }
5848
5849   /* if right is bit then exchange them */
5850   if (AOP_TYPE (right) == AOP_CRY &&
5851       AOP_TYPE (left) != AOP_CRY)
5852     {
5853       operand *tmp = right;
5854       right = left;
5855       left = tmp;
5856     }
5857   if (AOP_TYPE (right) == AOP_LIT)
5858     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5859
5860   size = AOP_SIZE (result);
5861
5862   // if(bit ^ yy)
5863   // xx = bit ^ yy;
5864   if (AOP_TYPE (left) == AOP_CRY)
5865     {
5866       if (AOP_TYPE (right) == AOP_LIT)
5867         {
5868           // c = bit & literal;
5869           if (lit >> 1)
5870             {
5871               // lit>>1  != 0 => result = 1
5872               if (AOP_TYPE (result) == AOP_CRY)
5873                 {
5874                   if (size)
5875                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5876                   else if (ifx)
5877                     continueIfTrue (ifx);
5878                   goto release;
5879                 }
5880               emitcode ("setb", "c");
5881             }
5882           else
5883             {
5884               // lit == (0 or 1)
5885               if (lit == 0)
5886                 {
5887                   // lit == 0, result = left
5888                   if (size && sameRegs (AOP (result), AOP (left)))
5889                     goto release;
5890                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5891                 }
5892               else
5893                 {
5894                   // lit == 1, result = not(left)
5895                   if (size && sameRegs (AOP (result), AOP (left)))
5896                     {
5897                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5898                       goto release;
5899                     }
5900                   else
5901                     {
5902                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5903                       emitcode ("cpl", "c");
5904                     }
5905                 }
5906             }
5907
5908         }
5909       else
5910         {
5911           // right != literal
5912           symbol *tlbl = newiTempLabel (NULL);
5913           if (AOP_TYPE (right) == AOP_CRY)
5914             {
5915               // c = bit ^ bit;
5916               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5917             }
5918           else
5919             {
5920               int sizer = AOP_SIZE (right);
5921               // c = bit ^ val
5922               // if val>>1 != 0, result = 1
5923               emitcode ("setb", "c");
5924               while (sizer)
5925                 {
5926                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5927                   if (sizer == 1)
5928                     // test the msb of the lsb
5929                     emitcode ("anl", "a,#0xfe");
5930                   emitcode ("jnz", "%05d$", tlbl->key + 100);
5931                   sizer--;
5932                 }
5933               // val = (0,1)
5934               emitcode ("rrc", "a");
5935             }
5936           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5937           emitcode ("cpl", "c");
5938           emitcode ("", "%05d$:", (tlbl->key + 100));
5939         }
5940       // bit = c
5941       // val = c
5942       if (size)
5943         outBitC (result);
5944       // if(bit | ...)
5945       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5946         genIfxJump (ifx, "c");
5947       goto release;
5948     }
5949
5950   if (sameRegs (AOP (result), AOP (left)))
5951     {
5952       /* if left is same as result */
5953       for (; size--; offset++)
5954         {
5955           if (AOP_TYPE (right) == AOP_LIT)
5956             {
5957               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5958                 continue;
5959               else if (IS_AOP_PREG (left))
5960                 {
5961                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5962                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5963                   aopPut (AOP (result), "a", offset);
5964                 }
5965               else
5966                 emitcode ("xrl", "%s,%s",
5967                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5968                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5969             }
5970           else
5971             {
5972               if (AOP_TYPE (left) == AOP_ACC)
5973                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5974               else
5975                 {
5976                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5977                   if (IS_AOP_PREG (left))
5978                     {
5979                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5980                       aopPut (AOP (result), "a", offset);
5981                     }
5982                   else
5983                     emitcode ("xrl", "%s,a",
5984                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5985                 }
5986             }
5987         }
5988     }
5989   else
5990     {
5991       // left & result in different registers
5992       if (AOP_TYPE (result) == AOP_CRY)
5993         {
5994           // result = bit
5995           // if(size), result in bit
5996           // if(!size && ifx), conditional oper: if(left ^ right)
5997           symbol *tlbl = newiTempLabel (NULL);
5998           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5999           if (size)
6000             emitcode ("setb", "c");
6001           while (sizer--)
6002             {
6003               if ((AOP_TYPE (right) == AOP_LIT) &&
6004                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6005                 {
6006                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6007                 }
6008               else
6009                 {
6010                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6011                     emitcode ("xrl", "a,%s",
6012                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6013                   } else {
6014                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6015                     emitcode ("xrl", "a,%s",
6016                               aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6017                   }
6018                 }
6019               emitcode ("jnz", "%05d$", tlbl->key + 100);
6020               offset++;
6021             }
6022           if (size)
6023             {
6024               CLRC;
6025               emitcode ("", "%05d$:", tlbl->key + 100);
6026               outBitC (result);
6027             }
6028           else if (ifx)
6029             jmpTrueOrFalse (ifx, tlbl);
6030         }
6031       else
6032         for (; (size--); offset++)
6033           {
6034             // normal case
6035             // result = left & right
6036             if (AOP_TYPE (right) == AOP_LIT)
6037               {
6038                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6039                   {
6040                     aopPut (AOP (result),
6041                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6042                             offset);
6043                     continue;
6044                   }
6045                 D (emitcode (";", "better literal XOR.");
6046                   );
6047                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6048                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6049                                                   FALSE, FALSE, FALSE));
6050               }
6051             else
6052               {
6053                 // faster than result <- left, anl result,right
6054                 // and better if result is SFR
6055                 if (AOP_TYPE (left) == AOP_ACC)
6056                   {
6057                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6058                                                      FALSE, FALSE, FALSE));
6059                   }
6060                 else
6061                   {
6062                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6063                     emitcode ("xrl", "a,%s",
6064                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6065                   }
6066               }
6067             aopPut (AOP (result), "a", offset);
6068           }
6069     }
6070
6071 release:
6072   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6073   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6074   freeAsmop (result, NULL, ic, TRUE);
6075 }
6076
6077 /*-----------------------------------------------------------------*/
6078 /* genInline - write the inline code out                           */
6079 /*-----------------------------------------------------------------*/
6080 static void
6081 genInline (iCode * ic)
6082 {
6083   char *buffer, *bp, *bp1;
6084
6085   D (emitcode (";", "genInline ");
6086     );
6087
6088   _G.inLine += (!options.asmpeep);
6089
6090   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6091   strcpy (buffer, IC_INLINE (ic));
6092
6093   /* emit each line as a code */
6094   while (*bp)
6095     {
6096       if (*bp == '\n')
6097         {
6098           *bp++ = '\0';
6099           emitcode (bp1, "");
6100           bp1 = bp;
6101         }
6102       else
6103         {
6104           if (*bp == ':')
6105             {
6106               bp++;
6107               *bp = '\0';
6108               bp++;
6109               emitcode (bp1, "");
6110               bp1 = bp;
6111             }
6112           else
6113             bp++;
6114         }
6115     }
6116   if (bp1 != bp)
6117     emitcode (bp1, "");
6118   /*     emitcode("",buffer); */
6119   _G.inLine -= (!options.asmpeep);
6120 }
6121
6122 /*-----------------------------------------------------------------*/
6123 /* genRRC - rotate right with carry                                */
6124 /*-----------------------------------------------------------------*/
6125 static void
6126 genRRC (iCode * ic)
6127 {
6128   operand *left, *result;
6129   int size, offset = 0;
6130   char *l;
6131
6132   D (emitcode (";", "genRRC ");
6133     );
6134
6135   /* rotate right with carry */
6136   left = IC_LEFT (ic);
6137   result = IC_RESULT (ic);
6138   aopOp (left, ic, FALSE, FALSE);
6139   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6140
6141   /* move it to the result */
6142   size = AOP_SIZE (result);
6143   offset = size - 1;
6144   CLRC;
6145
6146   _startLazyDPSEvaluation ();
6147   while (size--)
6148     {
6149       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6150       MOVA (l);
6151       emitcode ("rrc", "a");
6152       if (AOP_SIZE (result) > 1)
6153         aopPut (AOP (result), "a", offset--);
6154     }
6155   _endLazyDPSEvaluation ();
6156
6157   /* now we need to put the carry into the
6158      highest order byte of the result */
6159   if (AOP_SIZE (result) > 1)
6160     {
6161       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6162       MOVA (l);
6163     }
6164   emitcode ("mov", "acc.7,c");
6165   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6166   freeAsmop (left, NULL, ic, TRUE);
6167   freeAsmop (result, NULL, ic, TRUE);
6168 }
6169
6170 /*-----------------------------------------------------------------*/
6171 /* genRLC - generate code for rotate left with carry               */
6172 /*-----------------------------------------------------------------*/
6173 static void
6174 genRLC (iCode * ic)
6175 {
6176   operand *left, *result;
6177   int size, offset = 0;
6178   char *l;
6179
6180   D (emitcode (";", "genRLC ");
6181     );
6182
6183   /* rotate right with carry */
6184   left = IC_LEFT (ic);
6185   result = IC_RESULT (ic);
6186   aopOp (left, ic, FALSE, FALSE);
6187   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6188
6189   /* move it to the result */
6190   size = AOP_SIZE (result);
6191   offset = 0;
6192   if (size--)
6193     {
6194       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6195       MOVA (l);
6196       emitcode ("add", "a,acc");
6197       if (AOP_SIZE (result) > 1)
6198         {
6199           aopPut (AOP (result), "a", offset++);
6200         }
6201
6202       _startLazyDPSEvaluation ();
6203       while (size--)
6204         {
6205           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6206           MOVA (l);
6207           emitcode ("rlc", "a");
6208           if (AOP_SIZE (result) > 1)
6209             aopPut (AOP (result), "a", offset++);
6210         }
6211       _endLazyDPSEvaluation ();
6212     }
6213   /* now we need to put the carry into the
6214      highest order byte of the result */
6215   if (AOP_SIZE (result) > 1)
6216     {
6217       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6218       MOVA (l);
6219     }
6220   emitcode ("mov", "acc.0,c");
6221   aopPut (AOP (result), "a", 0);
6222   freeAsmop (left, NULL, ic, TRUE);
6223   freeAsmop (result, NULL, ic, TRUE);
6224 }
6225
6226 /*-----------------------------------------------------------------*/
6227 /* genGetHbit - generates code get highest order bit               */
6228 /*-----------------------------------------------------------------*/
6229 static void
6230 genGetHbit (iCode * ic)
6231 {
6232   operand *left, *result;
6233   left = IC_LEFT (ic);
6234   result = IC_RESULT (ic);
6235   aopOp (left, ic, FALSE, FALSE);
6236   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6237
6238   D (emitcode (";", "genGetHbit ");
6239     );
6240
6241   /* get the highest order byte into a */
6242   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6243   if (AOP_TYPE (result) == AOP_CRY)
6244     {
6245       emitcode ("rlc", "a");
6246       outBitC (result);
6247     }
6248   else
6249     {
6250       emitcode ("rl", "a");
6251       emitcode ("anl", "a,#0x01");
6252       outAcc (result);
6253     }
6254
6255
6256   freeAsmop (left, NULL, ic, TRUE);
6257   freeAsmop (result, NULL, ic, TRUE);
6258 }
6259
6260 /*-----------------------------------------------------------------*/
6261 /* AccRol - rotate left accumulator by known count                 */
6262 /*-----------------------------------------------------------------*/
6263 static void
6264 AccRol (int shCount)
6265 {
6266   shCount &= 0x0007;            // shCount : 0..7
6267
6268   switch (shCount)
6269     {
6270     case 0:
6271       break;
6272     case 1:
6273       emitcode ("rl", "a");
6274       break;
6275     case 2:
6276       emitcode ("rl", "a");
6277       emitcode ("rl", "a");
6278       break;
6279     case 3:
6280       emitcode ("swap", "a");
6281       emitcode ("rr", "a");
6282       break;
6283     case 4:
6284       emitcode ("swap", "a");
6285       break;
6286     case 5:
6287       emitcode ("swap", "a");
6288       emitcode ("rl", "a");
6289       break;
6290     case 6:
6291       emitcode ("rr", "a");
6292       emitcode ("rr", "a");
6293       break;
6294     case 7:
6295       emitcode ("rr", "a");
6296       break;
6297     }
6298 }
6299
6300 /*-----------------------------------------------------------------*/
6301 /* AccLsh - left shift accumulator by known count                  */
6302 /*-----------------------------------------------------------------*/
6303 static void
6304 AccLsh (int shCount)
6305 {
6306   if (shCount != 0)
6307     {
6308       if (shCount == 1)
6309         emitcode ("add", "a,acc");
6310       else if (shCount == 2)
6311         {
6312           emitcode ("add", "a,acc");
6313           emitcode ("add", "a,acc");
6314         }
6315       else
6316         {
6317           /* rotate left accumulator */
6318           AccRol (shCount);
6319           /* and kill the lower order bits */
6320           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6321         }
6322     }
6323 }
6324
6325 /*-----------------------------------------------------------------*/
6326 /* AccRsh - right shift accumulator by known count                 */
6327 /*-----------------------------------------------------------------*/
6328 static void
6329 AccRsh (int shCount)
6330 {
6331   if (shCount != 0)
6332     {
6333       if (shCount == 1)
6334         {
6335           CLRC;
6336           emitcode ("rrc", "a");
6337         }
6338       else
6339         {
6340           /* rotate right accumulator */
6341           AccRol (8 - shCount);
6342           /* and kill the higher order bits */
6343           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6344         }
6345     }
6346 }
6347
6348 #ifdef BETTER_LITERAL_SHIFT
6349 /*-----------------------------------------------------------------*/
6350 /* AccSRsh - signed right shift accumulator by known count                 */
6351 /*-----------------------------------------------------------------*/
6352 static void
6353 AccSRsh (int shCount)
6354 {
6355   symbol *tlbl;
6356   if (shCount != 0)
6357     {
6358       if (shCount == 1)
6359         {
6360           emitcode ("mov", "c,acc.7");
6361           emitcode ("rrc", "a");
6362         }
6363       else if (shCount == 2)
6364         {
6365           emitcode ("mov", "c,acc.7");
6366           emitcode ("rrc", "a");
6367           emitcode ("mov", "c,acc.7");
6368           emitcode ("rrc", "a");
6369         }
6370       else
6371         {
6372           tlbl = newiTempLabel (NULL);
6373           /* rotate right accumulator */
6374           AccRol (8 - shCount);
6375           /* and kill the higher order bits */
6376           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6377           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6378           emitcode ("orl", "a,#0x%02x",
6379                     (unsigned char) ~SRMask[shCount]);
6380           emitcode ("", "%05d$:", tlbl->key + 100);
6381         }
6382     }
6383 }
6384 #endif
6385
6386 #ifdef BETTER_LITERAL_SHIFT
6387 /*-----------------------------------------------------------------*/
6388 /* shiftR1Left2Result - shift right one byte from left to result   */
6389 /*-----------------------------------------------------------------*/
6390 static void
6391 shiftR1Left2Result (operand * left, int offl,
6392                     operand * result, int offr,
6393                     int shCount, int sign)
6394 {
6395   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6396   /* shift right accumulator */
6397   if (sign)
6398     AccSRsh (shCount);
6399   else
6400     AccRsh (shCount);
6401   aopPut (AOP (result), "a", offr);
6402 }
6403 #endif
6404
6405 #ifdef BETTER_LITERAL_SHIFT
6406 /*-----------------------------------------------------------------*/
6407 /* shiftL1Left2Result - shift left one byte from left to result    */
6408 /*-----------------------------------------------------------------*/
6409 static void
6410 shiftL1Left2Result (operand * left, int offl,
6411                     operand * result, int offr, int shCount)
6412 {
6413   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6414   /* shift left accumulator */
6415   AccLsh (shCount);
6416   aopPut (AOP (result), "a", offr);
6417 }
6418 #endif
6419
6420 #ifdef BETTER_LITERAL_SHIFT
6421 /*-----------------------------------------------------------------*/
6422 /* movLeft2Result - move byte from left to result                  */
6423 /*-----------------------------------------------------------------*/
6424 static void
6425 movLeft2Result (operand * left, int offl,
6426                 operand * result, int offr, int sign)
6427 {
6428   char *l;
6429   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6430   {
6431       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6432
6433       if (*l == '@' && (IS_AOP_PREG (result)))
6434       {
6435           emitcode ("mov", "a,%s", l);
6436           aopPut (AOP (result), "a", offr);
6437       }
6438       else
6439       {
6440           if (!sign)
6441           {
6442             aopPut (AOP (result), l, offr);
6443           }
6444           else
6445             {
6446               /* MSB sign in acc.7 ! */
6447               if (getDataSize (left) == offl + 1)
6448                 {
6449                   emitcode ("mov", "a,%s", l);
6450                   aopPut (AOP (result), "a", offr);
6451                 }
6452             }
6453       }
6454   }
6455 }
6456 #endif
6457
6458 #ifdef BETTER_LITERAL_SHIFT
6459 /*-----------------------------------------------------------------*/
6460 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6461 /*-----------------------------------------------------------------*/
6462 static void
6463 AccAXRrl1 (char *x)
6464 {
6465   emitcode ("rrc", "a");
6466   emitcode ("xch", "a,%s", x);
6467   emitcode ("rrc", "a");
6468   emitcode ("xch", "a,%s", x);
6469 }
6470 #endif
6471
6472 #ifdef BETTER_LITERAL_SHIFT
6473 //REMOVE ME!!!
6474 /*-----------------------------------------------------------------*/
6475 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6476 /*-----------------------------------------------------------------*/
6477 static void
6478 AccAXLrl1 (char *x)
6479 {
6480   emitcode ("xch", "a,%s", x);
6481   emitcode ("rlc", "a");
6482   emitcode ("xch", "a,%s", x);
6483   emitcode ("rlc", "a");
6484 }
6485 #endif
6486
6487 #ifdef BETTER_LITERAL_SHIFT
6488 /*-----------------------------------------------------------------*/
6489 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6490 /*-----------------------------------------------------------------*/
6491 static void
6492 AccAXLsh1 (char *x)
6493 {
6494   emitcode ("xch", "a,%s", x);
6495   emitcode ("add", "a,acc");
6496   emitcode ("xch", "a,%s", x);
6497   emitcode ("rlc", "a");
6498 }
6499 #endif
6500
6501 #ifdef BETTER_LITERAL_SHIFT
6502 /*-----------------------------------------------------------------*/
6503 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6504 /*-----------------------------------------------------------------*/
6505 static void
6506 AccAXLsh (char *x, int shCount)
6507 {
6508   switch (shCount)
6509     {
6510     case 0:
6511       break;
6512     case 1:
6513       AccAXLsh1 (x);
6514       break;
6515     case 2:
6516       AccAXLsh1 (x);
6517       AccAXLsh1 (x);
6518       break;
6519     case 3:
6520     case 4:
6521     case 5:                     // AAAAABBB:CCCCCDDD
6522
6523       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
6524
6525       emitcode ("anl", "a,#0x%02x",
6526                 SLMask[shCount]);       // BBB00000:CCCCCDDD
6527
6528       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
6529
6530       AccRol (shCount);         // DDDCCCCC:BBB00000
6531
6532       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
6533
6534       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
6535
6536       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
6537
6538       emitcode ("anl", "a,#0x%02x",
6539                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
6540
6541       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
6542
6543       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
6544
6545       break;
6546     case 6:                     // AAAAAABB:CCCCCCDD
6547       emitcode ("anl", "a,#0x%02x",
6548                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6549       emitcode ("mov", "c,acc.0");      // c = B
6550       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6551 #if 0
6552       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6553       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6554 #else
6555       emitcode("rrc","a"); 
6556       emitcode("xch","a,%s", x); 
6557       emitcode("rrc","a"); 
6558       emitcode("mov","c,acc.0"); //<< get correct bit 
6559       emitcode("xch","a,%s", x); 
6560
6561       emitcode("rrc","a"); 
6562       emitcode("xch","a,%s", x); 
6563       emitcode("rrc","a"); 
6564       emitcode("xch","a,%s", x); 
6565 #endif
6566       break;
6567     case 7:                     // a:x <<= 7
6568
6569       emitcode ("anl", "a,#0x%02x",
6570                 SRMask[shCount]);       // 0000000B:CCCCCCCD
6571
6572       emitcode ("mov", "c,acc.0");      // c = B
6573
6574       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
6575
6576       AccAXRrl1 (x);            // BCCCCCCC:D0000000
6577
6578       break;
6579     default:
6580       break;
6581     }
6582 }
6583 #endif
6584
6585 #ifdef BETTER_LITERAL_SHIFT
6586 //REMOVE ME!!!
6587 /*-----------------------------------------------------------------*/
6588 /* AccAXRsh - right shift a:x known count (0..7)                   */
6589 /*-----------------------------------------------------------------*/
6590 static void
6591 AccAXRsh (char *x, int shCount)
6592 {
6593   switch (shCount)
6594     {
6595     case 0:
6596       break;
6597     case 1:
6598       CLRC;
6599       AccAXRrl1 (x);            // 0->a:x
6600
6601       break;
6602     case 2:
6603       CLRC;
6604       AccAXRrl1 (x);            // 0->a:x
6605
6606       CLRC;
6607       AccAXRrl1 (x);            // 0->a:x
6608
6609       break;
6610     case 3:
6611     case 4:
6612     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6613
6614       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
6615
6616       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6617
6618       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6619
6620       emitcode ("anl", "a,#0x%02x",
6621                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6622
6623       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6624
6625       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6626
6627       emitcode ("anl", "a,#0x%02x",
6628                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6629
6630       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6631
6632       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6633
6634       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
6635
6636       break;
6637     case 6:                     // AABBBBBB:CCDDDDDD
6638
6639       emitcode ("mov", "c,acc.7");
6640       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6641
6642       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6643
6644       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6645
6646       emitcode ("anl", "a,#0x%02x",
6647                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6648
6649       break;
6650     case 7:                     // ABBBBBBB:CDDDDDDD
6651
6652       emitcode ("mov", "c,acc.7");      // c = A
6653
6654       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6655
6656       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6657
6658       emitcode ("anl", "a,#0x%02x",
6659                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6660
6661       break;
6662     default:
6663       break;
6664     }
6665 }
6666 #endif
6667
6668 #ifdef BETTER_LITERAL_SHIFT
6669 /*-----------------------------------------------------------------*/
6670 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6671 /*-----------------------------------------------------------------*/
6672 static void
6673 AccAXRshS (char *x, int shCount)
6674 {
6675   symbol *tlbl;
6676   switch (shCount)
6677     {
6678     case 0:
6679       break;
6680     case 1:
6681       emitcode ("mov", "c,acc.7");
6682       AccAXRrl1 (x);            // s->a:x
6683
6684       break;
6685     case 2:
6686       emitcode ("mov", "c,acc.7");
6687       AccAXRrl1 (x);            // s->a:x
6688
6689       emitcode ("mov", "c,acc.7");
6690       AccAXRrl1 (x);            // s->a:x
6691
6692       break;
6693     case 3:
6694     case 4:
6695     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6696
6697       tlbl = newiTempLabel (NULL);
6698       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
6699
6700       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6701
6702       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6703
6704       emitcode ("anl", "a,#0x%02x",
6705                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6706
6707       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6708
6709       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6710
6711       emitcode ("anl", "a,#0x%02x",
6712                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6713
6714       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6715
6716       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6717
6718       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
6719
6720       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6721       emitcode ("orl", "a,#0x%02x",
6722                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
6723
6724       emitcode ("", "%05d$:", tlbl->key + 100);
6725       break;                    // SSSSAAAA:BBBCCCCC
6726
6727     case 6:                     // AABBBBBB:CCDDDDDD
6728
6729       tlbl = newiTempLabel (NULL);
6730       emitcode ("mov", "c,acc.7");
6731       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6732
6733       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6734
6735       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6736
6737       emitcode ("anl", "a,#0x%02x",
6738                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6739
6740       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6741       emitcode ("orl", "a,#0x%02x",
6742                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
6743
6744       emitcode ("", "%05d$:", tlbl->key + 100);
6745       break;
6746     case 7:                     // ABBBBBBB:CDDDDDDD
6747
6748       tlbl = newiTempLabel (NULL);
6749       emitcode ("mov", "c,acc.7");      // c = A
6750
6751       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6752
6753       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6754
6755       emitcode ("anl", "a,#0x%02x",
6756                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6757
6758       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6759       emitcode ("orl", "a,#0x%02x",
6760                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
6761
6762       emitcode ("", "%05d$:", tlbl->key + 100);
6763       break;
6764     default:
6765       break;
6766     }
6767 }
6768 #endif
6769
6770 #ifdef BETTER_LITERAL_SHIFT
6771 static void
6772 _loadLeftIntoAx(char    **lsb, 
6773                 operand *left, 
6774                 operand *result,
6775                 int     offl,
6776                 int     offr)
6777 {
6778   // Get the initial value from left into a pair of registers.
6779   // MSB must be in A, LSB can be any register.
6780   //
6781   // If the result is held in registers, it is an optimization
6782   // if the LSB can be held in the register which will hold the,
6783   // result LSB since this saves us from having to copy it into
6784   // the result following AccAXLsh.
6785   //
6786   // If the result is addressed indirectly, this is not a gain.
6787   if (AOP_NEEDSACC(result))
6788   {
6789        char *leftByte;
6790        
6791        _startLazyDPSEvaluation();
6792       if (AOP_TYPE(left) == AOP_DPTR2)
6793        {
6794            // Get MSB in A.
6795            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6796            // get LSB in DP2_RESULT_REG.
6797            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6798            assert(!strcmp(leftByte, DP2_RESULT_REG));
6799        }
6800        else
6801        {
6802            // get LSB into DP2_RESULT_REG
6803            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6804            if (strcmp(leftByte, DP2_RESULT_REG))
6805            {
6806                TR_AP("#7");
6807                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6808            }
6809            // And MSB in A.
6810            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6811            assert(strcmp(leftByte, DP2_RESULT_REG));
6812            MOVA(leftByte);
6813        }
6814        _endLazyDPSEvaluation();
6815        *lsb = DP2_RESULT_REG;
6816   }
6817   else
6818   {
6819       if (sameRegs (AOP (result), AOP (left)) &&
6820         ((offl + MSB16) == offr))
6821       {
6822           /* don't crash result[offr] */
6823           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6824           emitcode ("xch", "a,%s", 
6825                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6826       }
6827       else
6828       {
6829           movLeft2Result (left, offl, result, offr, 0);
6830           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6831       }
6832       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6833       assert(strcmp(*lsb,"a"));      
6834   }
6835 }
6836
6837 static void
6838 _storeAxResults(char    *lsb,
6839                 operand *result,
6840                 int     offr)
6841 {
6842   _startLazyDPSEvaluation();
6843   if (AOP_NEEDSACC(result))
6844   {
6845       /* We have to explicitly update the result LSB.
6846        */
6847       emitcode("xch","a,%s", lsb);
6848       aopPut(AOP(result), "a", offr);
6849       emitcode("mov","a,%s", lsb);
6850   }
6851   if (getDataSize (result) > 1)
6852   {
6853       aopPut (AOP (result), "a", offr + MSB16);
6854   }
6855   _endLazyDPSEvaluation();
6856 }
6857
6858 /*-----------------------------------------------------------------*/
6859 /* shiftL2Left2Result - shift left two bytes from left to result   */
6860 /*-----------------------------------------------------------------*/
6861 static void
6862 shiftL2Left2Result (operand * left, int offl,
6863                     operand * result, int offr, int shCount)
6864 {
6865   char *lsb;
6866
6867   _loadLeftIntoAx(&lsb, left, result, offl, offr);
6868   
6869   AccAXLsh (lsb, shCount);
6870   
6871   _storeAxResults(lsb, result, offr);
6872 }
6873 #endif
6874
6875 #ifdef BETTER_LITERAL_SHIFT
6876 /*-----------------------------------------------------------------*/
6877 /* shiftR2Left2Result - shift right two bytes from left to result  */
6878 /*-----------------------------------------------------------------*/
6879 static void
6880 shiftR2Left2Result (operand * left, int offl,
6881                     operand * result, int offr,
6882                     int shCount, int sign)
6883 {
6884   char *lsb;
6885   
6886   _loadLeftIntoAx(&lsb, left, result, offl, offr);
6887   
6888   /* a:x >> shCount (x = lsb(result)) */
6889   if (sign)
6890   {
6891      AccAXRshS(lsb, shCount);
6892   }
6893   else
6894   {
6895     AccAXRsh(lsb, shCount);
6896   }
6897   
6898   _storeAxResults(lsb, result, offr);
6899 }
6900 #endif
6901
6902 #if 0
6903 //REMOVE ME!!!
6904 /*-----------------------------------------------------------------*/
6905 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6906 /*-----------------------------------------------------------------*/
6907 static void
6908 shiftLLeftOrResult (operand * left, int offl,
6909                     operand * result, int offr, int shCount)
6910 {
6911   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6912   /* shift left accumulator */
6913   AccLsh (shCount);
6914   /* or with result */
6915   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6916   /* back to result */
6917   aopPut (AOP (result), "a", offr);
6918 }
6919 #endif
6920
6921 #if 0
6922 //REMOVE ME!!!
6923 /*-----------------------------------------------------------------*/
6924 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6925 /*-----------------------------------------------------------------*/
6926 static void
6927 shiftRLeftOrResult (operand * left, int offl,
6928                     operand * result, int offr, int shCount)
6929 {
6930   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6931   /* shift right accumulator */
6932   AccRsh (shCount);
6933   /* or with result */
6934   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6935   /* back to result */
6936   aopPut (AOP (result), "a", offr);
6937 }
6938 #endif
6939
6940 #ifdef BETTER_LITERAL_SHIFT
6941 /*-----------------------------------------------------------------*/
6942 /* genlshOne - left shift a one byte quantity by known count       */
6943 /*-----------------------------------------------------------------*/
6944 static void
6945 genlshOne (operand * result, operand * left, int shCount)
6946 {
6947   D (emitcode (";", "genlshOne "););
6948   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6949 }
6950 #endif
6951
6952 #ifdef BETTER_LITERAL_SHIFT
6953 /*-----------------------------------------------------------------*/
6954 /* genlshTwo - left shift two bytes by known amount != 0           */
6955 /*-----------------------------------------------------------------*/
6956 static void
6957 genlshTwo (operand * result, operand * left, int shCount)
6958 {
6959   int size;
6960
6961   D (emitcode (";", "genlshTwo "););
6962
6963   size = getDataSize (result);
6964
6965   /* if shCount >= 8 */
6966   if (shCount >= 8)
6967   {
6968       shCount -= 8;
6969
6970       _startLazyDPSEvaluation();
6971
6972       if (size > 1)
6973         {
6974           if (shCount)
6975           {
6976             _endLazyDPSEvaluation();
6977             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6978             aopPut (AOP (result), zero, LSB);       
6979           }
6980           else
6981           {
6982             movLeft2Result (left, LSB, result, MSB16, 0);
6983             aopPut (AOP (result), zero, LSB);
6984             _endLazyDPSEvaluation();
6985           }
6986         }
6987         else
6988         {
6989           aopPut (AOP (result), zero, LSB);
6990           _endLazyDPSEvaluation();
6991         }
6992   }
6993
6994   /*  1 <= shCount <= 7 */
6995   else
6996     {
6997       if (size == 1)
6998       {
6999         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7000       }
7001       else
7002       {
7003         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7004       }
7005     }
7006 }
7007 #endif
7008
7009 #if 0
7010 //REMOVE ME!!!
7011 /*-----------------------------------------------------------------*/
7012 /* shiftLLong - shift left one long from left to result            */
7013 /* offl = LSB or MSB16                                             */
7014 /*-----------------------------------------------------------------*/
7015 static void
7016 shiftLLong (operand * left, operand * result, int offr)
7017 {
7018   char *l;
7019   int size = AOP_SIZE (result);
7020
7021   if (size >= LSB + offr)
7022     {
7023       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7024       MOVA (l);
7025       emitcode ("add", "a,acc");
7026       if (sameRegs (AOP (left), AOP (result)) &&
7027           size >= MSB16 + offr && offr != LSB)
7028         emitcode ("xch", "a,%s",
7029                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7030       else
7031         aopPut (AOP (result), "a", LSB + offr);
7032     }
7033
7034   if (size >= MSB16 + offr)
7035     {
7036       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7037         {
7038           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7039           MOVA (l);
7040         }
7041       emitcode ("rlc", "a");
7042       if (sameRegs (AOP (left), AOP (result)) &&
7043           size >= MSB24 + offr && offr != LSB)
7044         emitcode ("xch", "a,%s",
7045                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7046       else
7047         aopPut (AOP (result), "a", MSB16 + offr);
7048     }
7049
7050   if (size >= MSB24 + offr)
7051     {
7052       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7053         {
7054           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7055           MOVA (l);
7056         }
7057       emitcode ("rlc", "a");
7058       if (sameRegs (AOP (left), AOP (result)) &&
7059           size >= MSB32 + offr && offr != LSB)
7060         emitcode ("xch", "a,%s",
7061                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7062       else
7063         aopPut (AOP (result), "a", MSB24 + offr);
7064     }
7065
7066   if (size > MSB32 + offr)
7067     {
7068       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7069         {
7070           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7071           MOVA (l);
7072         }
7073       emitcode ("rlc", "a");
7074       aopPut (AOP (result), "a", MSB32 + offr);
7075     }
7076   if (offr != LSB)
7077     aopPut (AOP (result), zero, LSB);
7078 }
7079 #endif
7080
7081 #if 0
7082 //REMOVE ME!!!
7083 /*-----------------------------------------------------------------*/
7084 /* genlshFour - shift four byte by a known amount != 0             */
7085 /*-----------------------------------------------------------------*/
7086 static void
7087 genlshFour (operand * result, operand * left, int shCount)
7088 {
7089   int size;
7090
7091   D (emitcode (";", "genlshFour ");
7092     );
7093
7094   size = AOP_SIZE (result);
7095
7096   /* if shifting more that 3 bytes */
7097   if (shCount >= 24)
7098     {
7099       shCount -= 24;
7100       if (shCount)
7101         /* lowest order of left goes to the highest
7102            order of the destination */
7103         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7104       else
7105         movLeft2Result (left, LSB, result, MSB32, 0);
7106       aopPut (AOP (result), zero, LSB);
7107       aopPut (AOP (result), zero, MSB16);
7108       aopPut (AOP (result), zero, MSB24);
7109       return;
7110     }
7111
7112   /* more than two bytes */
7113   else if (shCount >= 16)
7114     {
7115       /* lower order two bytes goes to higher order two bytes */
7116       shCount -= 16;
7117       /* if some more remaining */
7118       if (shCount)
7119         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7120       else
7121         {
7122           movLeft2Result (left, MSB16, result, MSB32, 0);
7123           movLeft2Result (left, LSB, result, MSB24, 0);
7124         }
7125       aopPut (AOP (result), zero, MSB16);
7126       aopPut (AOP (result), zero, LSB);
7127       return;
7128     }
7129
7130   /* if more than 1 byte */
7131   else if (shCount >= 8)
7132     {
7133       /* lower order three bytes goes to higher order  three bytes */
7134       shCount -= 8;
7135       if (size == 2)
7136         {
7137           if (shCount)
7138             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7139           else
7140             movLeft2Result (left, LSB, result, MSB16, 0);
7141         }
7142       else
7143         {                       /* size = 4 */
7144           if (shCount == 0)
7145             {
7146               movLeft2Result (left, MSB24, result, MSB32, 0);
7147               movLeft2Result (left, MSB16, result, MSB24, 0);
7148               movLeft2Result (left, LSB, result, MSB16, 0);
7149               aopPut (AOP (result), zero, LSB);
7150             }
7151           else if (shCount == 1)
7152             shiftLLong (left, result, MSB16);
7153           else
7154             {
7155               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7156               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7157               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7158               aopPut (AOP (result), zero, LSB);
7159             }
7160         }
7161     }
7162
7163   /* 1 <= shCount <= 7 */
7164   else if (shCount <= 2)
7165     {
7166       shiftLLong (left, result, LSB);
7167       if (shCount == 2)
7168         shiftLLong (result, result, LSB);
7169     }
7170   /* 3 <= shCount <= 7, optimize */
7171   else
7172     {
7173       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7174       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7175       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7176     }
7177 }
7178 #endif
7179
7180 #ifdef BETTER_LITERAL_SHIFT
7181 /*-----------------------------------------------------------------*/
7182 /* genLeftShiftLiteral - left shifting by known count              */
7183 /*-----------------------------------------------------------------*/
7184 static bool
7185 genLeftShiftLiteral (operand * left,
7186                      operand * right,
7187                      operand * result,
7188                      iCode * ic)
7189 {
7190   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7191   int size;
7192
7193   size = getSize (operandType (result));
7194
7195   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7196
7197   /* We only handle certain easy cases so far. */
7198   if ((shCount != 0)
7199    && (shCount < (size * 8))
7200    && (size != 1)
7201    && (size != 2))
7202   {
7203       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7204       return FALSE;
7205   }
7206
7207   freeAsmop (right, NULL, ic, TRUE);
7208
7209   aopOp(left, ic, FALSE, FALSE);
7210   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7211
7212 #if 1 // debug spew
7213   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7214   {
7215         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7216         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7217         {
7218            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7219         }
7220   }
7221   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7222   {
7223         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7224         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7225         {
7226            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7227         }       
7228   }  
7229 #endif
7230   
7231 #if VIEW_SIZE
7232   emitcode ("; shift left ", "result %d, left %d", size,
7233             AOP_SIZE (left));
7234 #endif
7235
7236   /* I suppose that the left size >= result size */
7237   if (shCount == 0)
7238   {
7239         _startLazyDPSEvaluation();
7240         while (size--)
7241         {
7242           movLeft2Result (left, size, result, size, 0);
7243         }
7244         _endLazyDPSEvaluation();
7245   }
7246   else if (shCount >= (size * 8))
7247   {
7248     _startLazyDPSEvaluation();
7249     while (size--)
7250     {
7251       aopPut (AOP (result), zero, size);
7252     }
7253     _endLazyDPSEvaluation();
7254   }
7255   else
7256   {
7257       switch (size)
7258         {
7259         case 1:
7260           genlshOne (result, left, shCount);
7261           break;
7262
7263         case 2:
7264           genlshTwo (result, left, shCount);
7265           break;
7266 #if 0
7267         case 4:
7268           genlshFour (result, left, shCount);
7269           break;
7270 #endif
7271         default:
7272           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7273           break;
7274         }
7275     }
7276   freeAsmop (left, NULL, ic, TRUE);
7277   freeAsmop (result, NULL, ic, TRUE);
7278   return TRUE;
7279 }
7280 #endif
7281
7282 /*-----------------------------------------------------------------*/
7283 /* genLeftShift - generates code for left shifting                 */
7284 /*-----------------------------------------------------------------*/
7285 static void
7286 genLeftShift (iCode * ic)
7287 {
7288   operand *left, *right, *result;
7289   int size, offset;
7290   char *l;
7291   symbol *tlbl, *tlbl1;
7292
7293   D (emitcode (";", "genLeftShift "););
7294
7295   right = IC_RIGHT (ic);
7296   left = IC_LEFT (ic);
7297   result = IC_RESULT (ic);
7298
7299   aopOp (right, ic, FALSE, FALSE);
7300
7301
7302 #ifdef BETTER_LITERAL_SHIFT
7303   /* if the shift count is known then do it
7304      as efficiently as possible */
7305   if (AOP_TYPE (right) == AOP_LIT)
7306     {
7307       if (genLeftShiftLiteral (left, right, result, ic))
7308       {
7309         return;
7310       }
7311     }
7312 #endif
7313
7314   /* shift count is unknown then we have to form
7315      a loop get the loop count in B : Note: we take
7316      only the lower order byte since shifting
7317      more that 32 bits make no sense anyway, ( the
7318      largest size of an object can be only 32 bits ) */
7319
7320   if (AOP_TYPE (right) == AOP_LIT)
7321   {
7322       /* Really should be handled by genLeftShiftLiteral,
7323        * but since I'm too lazy to fix that today, at least we can make
7324        * some small improvement.
7325        */
7326        emitcode("mov", "b,#0x%02x",
7327                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7328   }
7329   else
7330   {
7331         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7332         emitcode ("inc", "b");
7333   }
7334   freeAsmop (right, NULL, ic, TRUE);
7335   aopOp (left, ic, FALSE, FALSE);
7336   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7337
7338   /* now move the left to the result if they are not the
7339      same */
7340   if (!sameRegs (AOP (left), AOP (result)) &&
7341       AOP_SIZE (result) > 1)
7342     {
7343
7344       size = AOP_SIZE (result);
7345       offset = 0;
7346       _startLazyDPSEvaluation ();
7347       while (size--)
7348         {
7349           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7350           if (*l == '@' && (IS_AOP_PREG (result)))
7351             {
7352
7353               emitcode ("mov", "a,%s", l);
7354               aopPut (AOP (result), "a", offset);
7355             }
7356           else
7357             aopPut (AOP (result), l, offset);
7358           offset++;
7359         }
7360       _endLazyDPSEvaluation ();
7361     }
7362
7363   tlbl = newiTempLabel (NULL);
7364   size = AOP_SIZE (result);
7365   offset = 0;
7366   tlbl1 = newiTempLabel (NULL);
7367
7368   /* if it is only one byte then */
7369   if (size == 1)
7370     {
7371       symbol *tlbl1 = newiTempLabel (NULL);
7372
7373       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7374       MOVA (l);
7375       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7376       emitcode ("", "%05d$:", tlbl->key + 100);
7377       emitcode ("add", "a,acc");
7378       emitcode ("", "%05d$:", tlbl1->key + 100);
7379       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7380       aopPut (AOP (result), "a", 0);
7381       goto release;
7382     }
7383
7384   reAdjustPreg (AOP (result));
7385
7386   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7387   emitcode ("", "%05d$:", tlbl->key + 100);
7388   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7389   MOVA (l);
7390   emitcode ("add", "a,acc");
7391   aopPut (AOP (result), "a", offset++);
7392   _startLazyDPSEvaluation ();
7393   while (--size)
7394     {
7395       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7396       MOVA (l);
7397       emitcode ("rlc", "a");
7398       aopPut (AOP (result), "a", offset++);
7399     }
7400   _endLazyDPSEvaluation ();
7401   reAdjustPreg (AOP (result));
7402
7403   emitcode ("", "%05d$:", tlbl1->key + 100);
7404   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7405 release:
7406   freeAsmop (left, NULL, ic, TRUE);
7407   freeAsmop (result, NULL, ic, TRUE);
7408 }
7409
7410 #ifdef BETTER_LITERAL_SHIFT
7411 /*-----------------------------------------------------------------*/
7412 /* genrshOne - right shift a one byte quantity by known count      */
7413 /*-----------------------------------------------------------------*/
7414 static void
7415 genrshOne (operand * result, operand * left,
7416            int shCount, int sign)
7417 {
7418   D (emitcode (";", "genrshOne"););
7419   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7420 }
7421 #endif
7422
7423 #ifdef BETTER_LITERAL_SHIFT
7424 /*-----------------------------------------------------------------*/
7425 /* genrshTwo - right shift two bytes by known amount != 0          */
7426 /*-----------------------------------------------------------------*/
7427 static void
7428 genrshTwo (operand * result, operand * left,
7429            int shCount, int sign)
7430 {
7431   D (emitcode (";", "genrshTwo"););
7432
7433   /* if shCount >= 8 */
7434   if (shCount >= 8)
7435     {
7436       shCount -= 8;
7437       _startLazyDPSEvaluation();
7438       if (shCount)
7439       {
7440         shiftR1Left2Result (left, MSB16, result, LSB,
7441                             shCount, sign);
7442       }                     
7443       else
7444       {
7445         movLeft2Result (left, MSB16, result, LSB, sign);
7446       }
7447       addSign (result, MSB16, sign);
7448       _endLazyDPSEvaluation();
7449     }
7450
7451   /*  1 <= shCount <= 7 */
7452   else
7453   {
7454     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7455   }
7456 }
7457 #endif
7458
7459 #if 0
7460 //REMOVE ME!!!
7461 /*-----------------------------------------------------------------*/
7462 /* shiftRLong - shift right one long from left to result           */
7463 /* offl = LSB or MSB16                                             */
7464 /*-----------------------------------------------------------------*/
7465 static void
7466 shiftRLong (operand * left, int offl,
7467             operand * result, int sign)
7468 {
7469   int isSameRegs=sameRegs(AOP(left),AOP(result));
7470
7471   if (isSameRegs && offl>1) {
7472     // we are in big trouble, but this shouldn't happen
7473     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7474   }
7475
7476   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7477   
7478   if (offl==MSB16) {
7479     // shift is > 8
7480     if (sign) {
7481       emitcode ("rlc", "a");
7482       emitcode ("subb", "a,acc");
7483       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7484     } else {
7485       aopPut (AOP(result), zero, MSB32);
7486     }
7487   }
7488
7489   if (!sign) {
7490     emitcode ("clr", "c");
7491   } else {
7492     emitcode ("mov", "c,acc.7");
7493   }
7494
7495   emitcode ("rrc", "a");
7496
7497   if (isSameRegs && offl==MSB16) {
7498     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7499   } else {
7500     aopPut (AOP (result), "a", MSB32);
7501     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7502   }
7503
7504   emitcode ("rrc", "a");
7505   if (isSameRegs && offl==1) {
7506     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7507   } else {
7508     aopPut (AOP (result), "a", MSB24);
7509     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7510   }
7511   emitcode ("rrc", "a");
7512   aopPut (AOP (result), "a", MSB16 - offl);
7513
7514   if (offl == LSB)
7515     {
7516       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7517       emitcode ("rrc", "a");
7518       aopPut (AOP (result), "a", LSB);
7519     }
7520 }
7521 #endif
7522
7523 #if 0
7524 //REMOVE ME!!!
7525 /*-----------------------------------------------------------------*/
7526 /* genrshFour - shift four byte by a known amount != 0             */
7527 /*-----------------------------------------------------------------*/
7528 static void
7529 genrshFour (operand * result, operand * left,
7530             int shCount, int sign)
7531 {
7532   D (emitcode (";", "genrshFour");
7533     );
7534
7535   /* if shifting more that 3 bytes */
7536   if (shCount >= 24)
7537     {
7538       shCount -= 24;
7539       if (shCount)
7540         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7541       else
7542         movLeft2Result (left, MSB32, result, LSB, sign);
7543       addSign (result, MSB16, sign);
7544     }
7545   else if (shCount >= 16)
7546     {
7547       shCount -= 16;
7548       if (shCount)
7549         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7550       else
7551         {
7552           movLeft2Result (left, MSB24, result, LSB, 0);
7553           movLeft2Result (left, MSB32, result, MSB16, sign);
7554         }
7555       addSign (result, MSB24, sign);
7556     }
7557   else if (shCount >= 8)
7558     {
7559       shCount -= 8;
7560       if (shCount == 1)
7561         shiftRLong (left, MSB16, result, sign);
7562       else if (shCount == 0)
7563         {
7564           movLeft2Result (left, MSB16, result, LSB, 0);
7565           movLeft2Result (left, MSB24, result, MSB16, 0);
7566           movLeft2Result (left, MSB32, result, MSB24, sign);
7567           addSign (result, MSB32, sign);
7568         }
7569       else
7570         {
7571           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7572           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7573           /* the last shift is signed */
7574           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7575           addSign (result, MSB32, sign);
7576         }
7577     }
7578   else
7579     {                           /* 1 <= shCount <= 7 */
7580       if (shCount <= 2)
7581         {
7582           shiftRLong (left, LSB, result, sign);
7583           if (shCount == 2)
7584             shiftRLong (result, LSB, result, sign);
7585         }
7586       else
7587         {
7588           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7589           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7590           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7591         }
7592     }
7593 }
7594 #endif
7595
7596 #ifdef BETTER_LITERAL_SHIFT
7597 /*-----------------------------------------------------------------*/
7598 /* genRightShiftLiteral - right shifting by known count            */
7599 /*-----------------------------------------------------------------*/
7600 static bool
7601 genRightShiftLiteral (operand * left,
7602                       operand * right,
7603                       operand * result,
7604                       iCode * ic,
7605                       int sign)
7606 {
7607   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7608   int size;
7609
7610   size = getSize (operandType (result));
7611
7612   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7613
7614   /* We only handle certain easy cases so far. */
7615   if ((shCount != 0)
7616    && (shCount < (size * 8))
7617    && (size != 1)
7618    && (size != 2))
7619   {
7620       D(emitcode (";", "genRightShiftLiteral wimping out"););   
7621       return FALSE;
7622   }
7623
7624   freeAsmop (right, NULL, ic, TRUE);
7625
7626   aopOp (left, ic, FALSE, FALSE);
7627   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7628
7629 #if VIEW_SIZE
7630   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7631             AOP_SIZE (left));
7632 #endif
7633
7634   /* test the LEFT size !!! */
7635
7636   /* I suppose that the left size >= result size */
7637   if (shCount == 0)
7638   {
7639       size = getDataSize (result);
7640       _startLazyDPSEvaluation();
7641       while (size--)
7642       {
7643         movLeft2Result (left, size, result, size, 0);
7644       }
7645       _endLazyDPSEvaluation();
7646   }
7647   else if (shCount >= (size * 8))
7648     {
7649       if (sign)
7650       {
7651         /* get sign in acc.7 */
7652         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7653       }
7654       addSign (result, LSB, sign);
7655     }
7656   else
7657     {
7658       switch (size)
7659         {
7660         case 1:
7661           genrshOne (result, left, shCount, sign);
7662           break;
7663
7664         case 2:
7665           genrshTwo (result, left, shCount, sign);
7666           break;
7667 #if 0
7668         case 4:
7669           genrshFour (result, left, shCount, sign);
7670           break;
7671 #endif    
7672         default:
7673           break;
7674         }
7675
7676       freeAsmop (left, NULL, ic, TRUE);
7677       freeAsmop (result, NULL, ic, TRUE);
7678     }
7679     return TRUE;
7680 }
7681 #endif
7682
7683 /*-----------------------------------------------------------------*/
7684 /* genSignedRightShift - right shift of signed number              */
7685 /*-----------------------------------------------------------------*/
7686 static void
7687 genSignedRightShift (iCode * ic)
7688 {
7689   operand *right, *left, *result;
7690   int size, offset;
7691   char *l;
7692   symbol *tlbl, *tlbl1;
7693
7694   D (emitcode (";", "genSignedRightShift "););
7695
7696   /* we do it the hard way put the shift count in b
7697      and loop thru preserving the sign */
7698
7699   right = IC_RIGHT (ic);
7700   left = IC_LEFT (ic);
7701   result = IC_RESULT (ic);
7702
7703   aopOp (right, ic, FALSE, FALSE);
7704
7705 #ifdef BETTER_LITERAL_SHIFT
7706   if (AOP_TYPE (right) == AOP_LIT)
7707     {
7708       if (genRightShiftLiteral (left, right, result, ic, 1))
7709       {
7710         return;
7711       }
7712     }
7713 #endif
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 genRightShiftLiteral,
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   /* mov the highest order bit to OVR */
7764   tlbl = newiTempLabel (NULL);
7765   tlbl1 = newiTempLabel (NULL);
7766
7767   size = AOP_SIZE (result);
7768   offset = size - 1;
7769   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7770   emitcode ("rlc", "a");
7771   emitcode ("mov", "ov,c");
7772   /* if it is only one byte then */
7773   if (size == 1)
7774     {
7775       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7776       MOVA (l);
7777       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7778       emitcode ("", "%05d$:", tlbl->key + 100);
7779       emitcode ("mov", "c,ov");
7780       emitcode ("rrc", "a");
7781       emitcode ("", "%05d$:", tlbl1->key + 100);
7782       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7783       aopPut (AOP (result), "a", 0);
7784       goto release;
7785     }
7786
7787   reAdjustPreg (AOP (result));
7788   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7789   emitcode ("", "%05d$:", tlbl->key + 100);
7790   emitcode ("mov", "c,ov");
7791   _startLazyDPSEvaluation ();
7792   while (size--)
7793     {
7794       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7795       MOVA (l);
7796       emitcode ("rrc", "a");
7797       aopPut (AOP (result), "a", offset--);
7798     }
7799   _endLazyDPSEvaluation ();
7800   reAdjustPreg (AOP (result));
7801   emitcode ("", "%05d$:", tlbl1->key + 100);
7802   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7803
7804 release:
7805   freeAsmop (left, NULL, ic, TRUE);
7806   freeAsmop (result, NULL, ic, TRUE);
7807 }
7808
7809 /*-----------------------------------------------------------------*/
7810 /* genRightShift - generate code for right shifting                */
7811 /*-----------------------------------------------------------------*/
7812 static void
7813 genRightShift (iCode * ic)
7814 {
7815   operand *right, *left, *result;
7816   sym_link *retype;
7817   int size, offset;
7818   char *l;
7819   symbol *tlbl, *tlbl1;
7820
7821   D (emitcode (";", "genRightShift "););
7822
7823   /* if signed then we do it the hard way preserve the
7824      sign bit moving it inwards */
7825   retype = getSpec (operandType (IC_RESULT (ic)));
7826
7827   if (!SPEC_USIGN (retype))
7828     {
7829       genSignedRightShift (ic);
7830       return;
7831     }
7832
7833   /* signed & unsigned types are treated the same : i.e. the
7834      signed is NOT propagated inwards : quoting from the
7835      ANSI - standard : "for E1 >> E2, is equivalent to division
7836      by 2**E2 if unsigned or if it has a non-negative value,
7837      otherwise the result is implementation defined ", MY definition
7838      is that the sign does not get propagated */
7839
7840   right = IC_RIGHT (ic);
7841   left = IC_LEFT (ic);
7842   result = IC_RESULT (ic);
7843
7844   aopOp (right, ic, FALSE, FALSE);
7845
7846 #ifdef BETTER_LITERAL_SHIFT
7847   /* if the shift count is known then do it
7848      as efficiently as possible */
7849   if (AOP_TYPE (right) == AOP_LIT)
7850     {
7851       if (genRightShiftLiteral (left, right, result, ic, 0))
7852       {
7853         return;
7854       }
7855     }
7856 #endif
7857
7858   /* shift count is unknown then we have to form
7859      a loop get the loop count in B : Note: we take
7860      only the lower order byte since shifting
7861      more that 32 bits make no sense anyway, ( the
7862      largest size of an object can be only 32 bits ) */
7863   
7864   if (AOP_TYPE (right) == AOP_LIT)
7865   {
7866       /* Really should be handled by genRightShiftLiteral,
7867        * but since I'm too lazy to fix that today, at least we can make
7868        * some small improvement.
7869        */
7870        emitcode("mov", "b,#0x%02x",
7871                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7872   }
7873   else
7874   {
7875         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7876         emitcode ("inc", "b");
7877   }
7878   freeAsmop (right, NULL, ic, TRUE);
7879   aopOp (left, ic, FALSE, FALSE);
7880   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7881
7882   /* now move the left to the result if they are not the
7883      same */
7884   if (!sameRegs (AOP (left), AOP (result)) &&
7885       AOP_SIZE (result) > 1)
7886     {
7887
7888       size = AOP_SIZE (result);
7889       offset = 0;
7890       _startLazyDPSEvaluation ();
7891       while (size--)
7892         {
7893           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7894           if (*l == '@' && IS_AOP_PREG (result))
7895             {
7896
7897               emitcode ("mov", "a,%s", l);
7898               aopPut (AOP (result), "a", offset);
7899             }
7900           else
7901             aopPut (AOP (result), l, offset);
7902           offset++;
7903         }
7904       _endLazyDPSEvaluation ();
7905     }
7906
7907   tlbl = newiTempLabel (NULL);
7908   tlbl1 = newiTempLabel (NULL);
7909   size = AOP_SIZE (result);
7910   offset = size - 1;
7911
7912   /* if it is only one byte then */
7913   if (size == 1)
7914     {
7915       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7916       MOVA (l);
7917       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7918       emitcode ("", "%05d$:", tlbl->key + 100);
7919       CLRC;
7920       emitcode ("rrc", "a");
7921       emitcode ("", "%05d$:", tlbl1->key + 100);
7922       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7923       aopPut (AOP (result), "a", 0);
7924       goto release;
7925     }
7926
7927   reAdjustPreg (AOP (result));
7928   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7929   emitcode ("", "%05d$:", tlbl->key + 100);
7930   CLRC;
7931   _startLazyDPSEvaluation ();
7932   while (size--)
7933     {
7934       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7935       MOVA (l);
7936       emitcode ("rrc", "a");
7937       aopPut (AOP (result), "a", offset--);
7938     }
7939   _endLazyDPSEvaluation ();
7940   reAdjustPreg (AOP (result));
7941
7942   emitcode ("", "%05d$:", tlbl1->key + 100);
7943   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7944
7945 release:
7946   freeAsmop (left, NULL, ic, TRUE);
7947   freeAsmop (result, NULL, ic, TRUE);
7948 }
7949
7950 /*-----------------------------------------------------------------*/
7951 /* genUnpackBits - generates code for unpacking bits               */
7952 /*-----------------------------------------------------------------*/
7953 static void
7954 genUnpackBits (operand * result, char *rname, int ptype)
7955 {
7956   int shCnt;
7957   int rlen = 0;
7958   sym_link *etype;
7959   int offset = 0;
7960
7961   D (emitcode (";", "genUnpackBits ");
7962     );
7963
7964   etype = getSpec (operandType (result));
7965
7966   /* read the first byte  */
7967   switch (ptype)
7968     {
7969
7970     case POINTER:
7971     case IPOINTER:
7972       emitcode ("mov", "a,@%s", rname);
7973       break;
7974
7975     case PPOINTER:
7976       emitcode ("movx", "a,@%s", rname);
7977       break;
7978
7979     case FPOINTER:
7980       emitcode ("movx", "a,@dptr");
7981       break;
7982
7983     case CPOINTER:
7984       emitcode ("clr", "a");
7985       emitcode ("movc", "a,@a+dptr");
7986       break;
7987
7988     case GPOINTER:
7989       emitcode ("lcall", "__gptrget");
7990       break;
7991     }
7992
7993   /* if we have bitdisplacement then it fits   */
7994   /* into this byte completely or if length is */
7995   /* less than a byte                          */
7996   if ((shCnt = SPEC_BSTR (etype)) ||
7997       (SPEC_BLEN (etype) <= 8))
7998     {
7999
8000       /* shift right acc */
8001       AccRsh (shCnt);
8002
8003       emitcode ("anl", "a,#0x%02x",
8004                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8005       aopPut (AOP (result), "a", offset);
8006       return;
8007     }
8008
8009   /* bit field did not fit in a byte  */
8010   rlen = SPEC_BLEN (etype) - 8;
8011   aopPut (AOP (result), "a", offset++);
8012
8013   while (1)
8014     {
8015
8016       switch (ptype)
8017         {
8018         case POINTER:
8019         case IPOINTER:
8020           emitcode ("inc", "%s", rname);
8021           emitcode ("mov", "a,@%s", rname);
8022           break;
8023
8024         case PPOINTER:
8025           emitcode ("inc", "%s", rname);
8026           emitcode ("movx", "a,@%s", rname);
8027           break;
8028
8029         case FPOINTER:
8030           emitcode ("inc", "dptr");
8031           emitcode ("movx", "a,@dptr");
8032           break;
8033
8034         case CPOINTER:
8035           emitcode ("clr", "a");
8036           emitcode ("inc", "dptr");
8037           emitcode ("movc", "a,@a+dptr");
8038           break;
8039
8040         case GPOINTER:
8041           emitcode ("inc", "dptr");
8042           emitcode ("lcall", "__gptrget");
8043           break;
8044         }
8045
8046       rlen -= 8;
8047       /* if we are done */
8048       if (rlen < 8)
8049         break;
8050
8051       aopPut (AOP (result), "a", offset++);
8052
8053     }
8054
8055   if (rlen)
8056     {
8057       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8058       aopPut (AOP (result), "a", offset);
8059     }
8060
8061   return;
8062 }
8063
8064
8065 /*-----------------------------------------------------------------*/
8066 /* genDataPointerGet - generates code when ptr offset is known     */
8067 /*-----------------------------------------------------------------*/
8068 static void
8069 genDataPointerGet (operand * left,
8070                    operand * result,
8071                    iCode * ic)
8072 {
8073   char *l;
8074   char buffer[256];
8075   int size, offset = 0;
8076   aopOp (result, ic, TRUE, FALSE);
8077
8078   /* get the string representation of the name */
8079   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8080   size = AOP_SIZE (result);
8081   _startLazyDPSEvaluation ();
8082   while (size--)
8083     {
8084       if (offset)
8085         sprintf (buffer, "(%s + %d)", l + 1, offset);
8086       else
8087         sprintf (buffer, "%s", l + 1);
8088       aopPut (AOP (result), buffer, offset++);
8089     }
8090   _endLazyDPSEvaluation ();
8091
8092   freeAsmop (left, NULL, ic, TRUE);
8093   freeAsmop (result, NULL, ic, TRUE);
8094 }
8095
8096 /*-----------------------------------------------------------------*/
8097 /* genNearPointerGet - emitcode for near pointer fetch             */
8098 /*-----------------------------------------------------------------*/
8099 static void
8100 genNearPointerGet (operand * left,
8101                    operand * result,
8102                    iCode * ic)
8103 {
8104   asmop *aop = NULL;
8105   regs *preg = NULL;
8106   char *rname;
8107   sym_link *rtype, *retype, *letype;
8108   sym_link *ltype = operandType (left);
8109   char buffer[80];
8110
8111   rtype = operandType (result);
8112   retype = getSpec (rtype);
8113   letype = getSpec (ltype);
8114
8115   aopOp (left, ic, FALSE, FALSE);
8116
8117   /* if left is rematerialisable and
8118      result is not bit variable type and
8119      the left is pointer to data space i.e
8120      lower 128 bytes of space */
8121   if (AOP_TYPE (left) == AOP_IMMD &&
8122       !IS_BITVAR (retype) &&
8123       !IS_BITVAR (letype) &&
8124       DCL_TYPE (ltype) == POINTER)
8125     {
8126       genDataPointerGet (left, result, ic);
8127       return;
8128     }
8129
8130   /* if the value is already in a pointer register
8131      then don't need anything more */
8132   if (!AOP_INPREG (AOP (left)))
8133     {
8134       /* otherwise get a free pointer register */
8135       aop = newAsmop (0);
8136       preg = getFreePtr (ic, &aop, FALSE);
8137       emitcode ("mov", "%s,%s",
8138                 preg->name,
8139                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8140       rname = preg->name;
8141     }
8142   else
8143     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8144
8145   freeAsmop (left, NULL, ic, TRUE);
8146   aopOp (result, ic, FALSE, FALSE);
8147
8148   /* if bitfield then unpack the bits */
8149   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8150     genUnpackBits (result, rname, POINTER);
8151   else
8152     {
8153       /* we have can just get the values */
8154       int size = AOP_SIZE (result);
8155       int offset = 0;
8156
8157       while (size--)
8158         {
8159           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8160             {
8161
8162               emitcode ("mov", "a,@%s", rname);
8163               aopPut (AOP (result), "a", offset);
8164             }
8165           else
8166             {
8167               sprintf (buffer, "@%s", rname);
8168               aopPut (AOP (result), buffer, offset);
8169             }
8170           offset++;
8171           if (size)
8172             emitcode ("inc", "%s", rname);
8173         }
8174     }
8175
8176   /* now some housekeeping stuff */
8177   if (aop)
8178     {
8179       /* we had to allocate for this iCode */
8180       freeAsmop (NULL, aop, ic, TRUE);
8181     }
8182   else
8183     {
8184       /* we did not allocate which means left
8185          already in a pointer register, then
8186          if size > 0 && this could be used again
8187          we have to point it back to where it
8188          belongs */
8189       if (AOP_SIZE (result) > 1 &&
8190           !OP_SYMBOL (left)->remat &&
8191           (OP_SYMBOL (left)->liveTo > ic->seq ||
8192            ic->depth))
8193         {
8194           int size = AOP_SIZE (result) - 1;
8195           while (size--)
8196             emitcode ("dec", "%s", rname);
8197         }
8198     }
8199
8200   /* done */
8201   freeAsmop (result, NULL, ic, TRUE);
8202
8203 }
8204
8205 /*-----------------------------------------------------------------*/
8206 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8207 /*-----------------------------------------------------------------*/
8208 static void
8209 genPagedPointerGet (operand * left,
8210                     operand * result,
8211                     iCode * ic)
8212 {
8213   asmop *aop = NULL;
8214   regs *preg = NULL;
8215   char *rname;
8216   sym_link *rtype, *retype, *letype;
8217
8218   rtype = operandType (result);
8219   retype = getSpec (rtype);
8220   letype = getSpec (operandType (left));
8221   aopOp (left, ic, FALSE, FALSE);
8222
8223   /* if the value is already in a pointer register
8224      then don't need anything more */
8225   if (!AOP_INPREG (AOP (left)))
8226     {
8227       /* otherwise get a free pointer register */
8228       aop = newAsmop (0);
8229       preg = getFreePtr (ic, &aop, FALSE);
8230       emitcode ("mov", "%s,%s",
8231                 preg->name,
8232                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8233       rname = preg->name;
8234     }
8235   else
8236     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8237
8238   freeAsmop (left, NULL, ic, TRUE);
8239   aopOp (result, ic, FALSE, FALSE);
8240
8241   /* if bitfield then unpack the bits */
8242   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8243     genUnpackBits (result, rname, PPOINTER);
8244   else
8245     {
8246       /* we have can just get the values */
8247       int size = AOP_SIZE (result);
8248       int offset = 0;
8249
8250       while (size--)
8251         {
8252
8253           emitcode ("movx", "a,@%s", rname);
8254           aopPut (AOP (result), "a", offset);
8255
8256           offset++;
8257
8258           if (size)
8259             emitcode ("inc", "%s", rname);
8260         }
8261     }
8262
8263   /* now some housekeeping stuff */
8264   if (aop)
8265     {
8266       /* we had to allocate for this iCode */
8267       freeAsmop (NULL, aop, ic, TRUE);
8268     }
8269   else
8270     {
8271       /* we did not allocate which means left
8272          already in a pointer register, then
8273          if size > 0 && this could be used again
8274          we have to point it back to where it
8275          belongs */
8276       if (AOP_SIZE (result) > 1 &&
8277           !OP_SYMBOL (left)->remat &&
8278           (OP_SYMBOL (left)->liveTo > ic->seq ||
8279            ic->depth))
8280         {
8281           int size = AOP_SIZE (result) - 1;
8282           while (size--)
8283             emitcode ("dec", "%s", rname);
8284         }
8285     }
8286
8287   /* done */
8288   freeAsmop (result, NULL, ic, TRUE);
8289
8290
8291 }
8292
8293 /*-----------------------------------------------------------------*/
8294 /* genFarPointerGet - gget value from far space                    */
8295 /*-----------------------------------------------------------------*/
8296 static void
8297 genFarPointerGet (operand * left,
8298                   operand * result, iCode * ic)
8299 {
8300   int size, offset;
8301   sym_link *retype = getSpec (operandType (result));
8302   sym_link *letype = getSpec (operandType (left));
8303   D (emitcode (";", "genFarPointerGet");
8304     );
8305
8306   aopOp (left, ic, FALSE, FALSE);
8307
8308   /* if the operand is already in dptr
8309      then we do nothing else we move the value to dptr */
8310   if (AOP_TYPE (left) != AOP_STR)
8311     {
8312       /* if this is remateriazable */
8313       if (AOP_TYPE (left) == AOP_IMMD)
8314         {
8315           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8316         }
8317       else
8318         {
8319           /* we need to get it byte by byte */
8320           _startLazyDPSEvaluation ();
8321           if (AOP_TYPE (left) != AOP_DPTR)
8322             {
8323               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8324               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8325               if (options.model == MODEL_FLAT24)
8326                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8327             }
8328           else
8329             {
8330               /* We need to generate a load to DPTR indirect through DPTR. */
8331               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8332                 );
8333               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8334               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8335               if (options.model == MODEL_FLAT24)
8336                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8337               emitcode ("pop", "dph");
8338               emitcode ("pop", "dpl");
8339             }
8340           _endLazyDPSEvaluation ();
8341         }
8342     }
8343   /* so dptr know contains the address */
8344   freeAsmop (left, NULL, ic, TRUE);
8345   aopOp (result, ic, FALSE, TRUE);
8346
8347   /* if bit then unpack */
8348   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8349     genUnpackBits (result, "dptr", FPOINTER);
8350   else
8351     {
8352       size = AOP_SIZE (result);
8353       offset = 0;
8354
8355       _startLazyDPSEvaluation ();
8356       while (size--)
8357         {
8358
8359           genSetDPTR (0);
8360           _flushLazyDPS ();
8361
8362           emitcode ("movx", "a,@dptr");
8363           if (size)
8364             emitcode ("inc", "dptr");
8365
8366           aopPut (AOP (result), "a", offset++);
8367         }
8368       _endLazyDPSEvaluation ();
8369     }
8370
8371   freeAsmop (result, NULL, ic, TRUE);
8372 }
8373
8374 /*-----------------------------------------------------------------*/
8375 /* emitcodePointerGet - gget value from code space                  */
8376 /*-----------------------------------------------------------------*/
8377 static void
8378 emitcodePointerGet (operand * left,
8379                     operand * result, iCode * ic)
8380 {
8381   int size, offset;
8382   sym_link *retype = getSpec (operandType (result));
8383
8384   aopOp (left, ic, FALSE, FALSE);
8385
8386   /* if the operand is already in dptr
8387      then we do nothing else we move the value to dptr */
8388   if (AOP_TYPE (left) != AOP_STR)
8389     {
8390       /* if this is remateriazable */
8391       if (AOP_TYPE (left) == AOP_IMMD)
8392         {
8393           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8394         }
8395       else
8396         {                       /* we need to get it byte by byte */
8397           _startLazyDPSEvaluation ();
8398           if (AOP_TYPE (left) != AOP_DPTR)
8399             {
8400               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8401               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8402               if (options.model == MODEL_FLAT24)
8403                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8404             }
8405           else
8406             {
8407               /* We need to generate a load to DPTR indirect through DPTR. */
8408               D (emitcode (";", "gencodePointerGet -- indirection special case.");
8409                 );
8410               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8411               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8412               if (options.model == MODEL_FLAT24)
8413                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8414               emitcode ("pop", "dph");
8415               emitcode ("pop", "dpl");
8416             }
8417           _endLazyDPSEvaluation ();
8418         }
8419     }
8420   /* so dptr know contains the address */
8421   freeAsmop (left, NULL, ic, TRUE);
8422   aopOp (result, ic, FALSE, TRUE);
8423
8424   /* if bit then unpack */
8425   if (IS_BITVAR (retype))
8426     genUnpackBits (result, "dptr", CPOINTER);
8427   else
8428     {
8429       size = AOP_SIZE (result);
8430       offset = 0;
8431
8432       _startLazyDPSEvaluation ();
8433       while (size--)
8434         {
8435           genSetDPTR (0);
8436           _flushLazyDPS ();
8437
8438           emitcode ("clr", "a");
8439           emitcode ("movc", "a,@a+dptr");
8440           if (size)
8441             emitcode ("inc", "dptr");
8442           aopPut (AOP (result), "a", offset++);
8443         }
8444       _endLazyDPSEvaluation ();
8445     }
8446
8447   freeAsmop (result, NULL, ic, TRUE);
8448 }
8449
8450 /*-----------------------------------------------------------------*/
8451 /* genGenPointerGet - gget value from generic pointer space        */
8452 /*-----------------------------------------------------------------*/
8453 static void
8454 genGenPointerGet (operand * left,
8455                   operand * result, iCode * ic)
8456 {
8457   int size, offset;
8458   sym_link *retype = getSpec (operandType (result));
8459   sym_link *letype = getSpec (operandType (left));
8460
8461   D (emitcode (";", "genGenPointerGet "); );
8462
8463   aopOp (left, ic, FALSE, TRUE);
8464
8465   /* if the operand is already in dptr
8466      then we do nothing else we move the value to dptr */
8467   if (AOP_TYPE (left) != AOP_STR)
8468     {
8469       /* if this is remateriazable */
8470       if (AOP_TYPE (left) == AOP_IMMD)
8471         {
8472           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8473           emitcode ("mov", "b,#%d", pointerCode (retype));
8474         }
8475       else
8476         {                       /* we need to get it byte by byte */
8477           _startLazyDPSEvaluation ();
8478           if (AOP(left)->type==AOP_DPTR2) {
8479             char *l;
8480             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8481             genSetDPTR(0);
8482             _flushLazyDPS();
8483             emitcode ("mov", "dpl,%s", l);
8484             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8485             genSetDPTR(0);
8486             _flushLazyDPS();
8487             emitcode ("mov", "dph,%s", l);
8488             if (options.model == MODEL_FLAT24) {
8489               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8490               genSetDPTR(0);
8491               _flushLazyDPS();
8492               emitcode ("mov", "dpx,%s", l);
8493               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8494             } else {
8495               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8496             }
8497           } else {
8498             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8499             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8500             if (options.model == MODEL_FLAT24) {
8501               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8502               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8503             } else {
8504               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8505             }
8506           }
8507           _endLazyDPSEvaluation ();
8508         }
8509     }
8510   /* so dptr know contains the address */
8511   freeAsmop (left, NULL, ic, TRUE);
8512   aopOp (result, ic, FALSE, TRUE);
8513
8514   /* if bit then unpack */
8515   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8516     genUnpackBits (result, "dptr", GPOINTER);
8517   else
8518     {
8519       size = AOP_SIZE (result);
8520       offset = 0;
8521
8522       while (size--)
8523         {
8524           emitcode ("lcall", "__gptrget");
8525           aopPut (AOP (result), "a", offset++);
8526           if (size)
8527             emitcode ("inc", "dptr");
8528         }
8529     }
8530
8531   freeAsmop (result, NULL, ic, TRUE);
8532 }
8533
8534 /*-----------------------------------------------------------------*/
8535 /* genPointerGet - generate code for pointer get                   */
8536 /*-----------------------------------------------------------------*/
8537 static void
8538 genPointerGet (iCode * ic)
8539 {
8540   operand *left, *result;
8541   sym_link *type, *etype;
8542   int p_type;
8543
8544   D (emitcode (";", "genPointerGet ");
8545     );
8546
8547   left = IC_LEFT (ic);
8548   result = IC_RESULT (ic);
8549
8550   /* depending on the type of pointer we need to
8551      move it to the correct pointer register */
8552   type = operandType (left);
8553   etype = getSpec (type);
8554   /* if left is of type of pointer then it is simple */
8555   if (IS_PTR (type) && !IS_FUNC (type->next))
8556     p_type = DCL_TYPE (type);
8557   else
8558     {
8559       /* we have to go by the storage class */
8560       p_type = PTR_TYPE (SPEC_OCLS (etype));
8561     }
8562
8563   /* now that we have the pointer type we assign
8564      the pointer values */
8565   switch (p_type)
8566     {
8567
8568     case POINTER:
8569     case IPOINTER:
8570       genNearPointerGet (left, result, ic);
8571       break;
8572
8573     case PPOINTER:
8574       genPagedPointerGet (left, result, ic);
8575       break;
8576
8577     case FPOINTER:
8578       genFarPointerGet (left, result, ic);
8579       break;
8580
8581     case CPOINTER:
8582       emitcodePointerGet (left, result, ic);
8583       break;
8584
8585     case GPOINTER:
8586       genGenPointerGet (left, result, ic);
8587       break;
8588     }
8589
8590 }
8591
8592 /*-----------------------------------------------------------------*/
8593 /* genPackBits - generates code for packed bit storage             */
8594 /*-----------------------------------------------------------------*/
8595 static void
8596 genPackBits (sym_link * etype,
8597              operand * right,
8598              char *rname, int p_type)
8599 {
8600   int shCount = 0;
8601   int offset = 0;
8602   int rLen = 0;
8603   int blen, bstr;
8604   char *l;
8605
8606   blen = SPEC_BLEN (etype);
8607   bstr = SPEC_BSTR (etype);
8608
8609   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8610   MOVA (l);
8611
8612   /* if the bit lenth is less than or    */
8613   /* it exactly fits a byte then         */
8614   if (SPEC_BLEN (etype) <= 8)
8615     {
8616       shCount = SPEC_BSTR (etype);
8617
8618       /* shift left acc */
8619       AccLsh (shCount);
8620
8621       if (SPEC_BLEN (etype) < 8)
8622         {                       /* if smaller than a byte */
8623
8624
8625           switch (p_type)
8626             {
8627             case POINTER:
8628               emitcode ("mov", "b,a");
8629               emitcode ("mov", "a,@%s", rname);
8630               break;
8631
8632             case FPOINTER:
8633               emitcode ("mov", "b,a");
8634               emitcode ("movx", "a,@dptr");
8635               break;
8636
8637             case GPOINTER:
8638               emitcode ("push", "b");
8639               emitcode ("push", "acc");
8640               emitcode ("lcall", "__gptrget");
8641               emitcode ("pop", "b");
8642               break;
8643             }
8644
8645           emitcode ("anl", "a,#0x%02x", (unsigned char)
8646                     ((unsigned char) (0xFF << (blen + bstr)) |
8647                      (unsigned char) (0xFF >> (8 - bstr))));
8648           emitcode ("orl", "a,b");
8649           if (p_type == GPOINTER)
8650             emitcode ("pop", "b");
8651         }
8652     }
8653
8654   switch (p_type)
8655     {
8656     case POINTER:
8657       emitcode ("mov", "@%s,a", rname);
8658       break;
8659
8660     case FPOINTER:
8661       emitcode ("movx", "@dptr,a");
8662       break;
8663
8664     case GPOINTER:
8665       emitcode ("lcall", "__gptrput");
8666       break;
8667     }
8668
8669   /* if we r done */
8670   if (SPEC_BLEN (etype) <= 8)
8671     return;
8672
8673   emitcode ("inc", "%s", rname);
8674   rLen = SPEC_BLEN (etype);
8675
8676   /* now generate for lengths greater than one byte */
8677   while (1)
8678     {
8679
8680       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8681
8682       rLen -= 8;
8683       if (rLen < 8)
8684         break;
8685
8686       switch (p_type)
8687         {
8688         case POINTER:
8689           if (*l == '@')
8690             {
8691               MOVA (l);
8692               emitcode ("mov", "@%s,a", rname);
8693             }
8694           else
8695             emitcode ("mov", "@%s,%s", rname, l);
8696           break;
8697
8698         case FPOINTER:
8699           MOVA (l);
8700           emitcode ("movx", "@dptr,a");
8701           break;
8702
8703         case GPOINTER:
8704           MOVA (l);
8705           emitcode ("lcall", "__gptrput");
8706           break;
8707         }
8708       emitcode ("inc", "%s", rname);
8709     }
8710
8711   MOVA (l);
8712
8713   /* last last was not complete */
8714   if (rLen)
8715     {
8716       /* save the byte & read byte */
8717       switch (p_type)
8718         {
8719         case POINTER:
8720           emitcode ("mov", "b,a");
8721           emitcode ("mov", "a,@%s", rname);
8722           break;
8723
8724         case FPOINTER:
8725           emitcode ("mov", "b,a");
8726           emitcode ("movx", "a,@dptr");
8727           break;
8728
8729         case GPOINTER:
8730           emitcode ("push", "b");
8731           emitcode ("push", "acc");
8732           emitcode ("lcall", "__gptrget");
8733           emitcode ("pop", "b");
8734           break;
8735         }
8736
8737       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8738       emitcode ("orl", "a,b");
8739     }
8740
8741   if (p_type == GPOINTER)
8742     emitcode ("pop", "b");
8743
8744   switch (p_type)
8745     {
8746
8747     case POINTER:
8748       emitcode ("mov", "@%s,a", rname);
8749       break;
8750
8751     case FPOINTER:
8752       emitcode ("movx", "@dptr,a");
8753       break;
8754
8755     case GPOINTER:
8756       emitcode ("lcall", "__gptrput");
8757       break;
8758     }
8759 }
8760 /*-----------------------------------------------------------------*/
8761 /* genDataPointerSet - remat pointer to data space                 */
8762 /*-----------------------------------------------------------------*/
8763 static void
8764 genDataPointerSet (operand * right,
8765                    operand * result,
8766                    iCode * ic)
8767 {
8768   int size, offset = 0;
8769   char *l, buffer[256];
8770
8771   aopOp (right, ic, FALSE, FALSE);
8772
8773   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8774   size = AOP_SIZE (right);
8775   while (size--)
8776     {
8777       if (offset)
8778         sprintf (buffer, "(%s + %d)", l + 1, offset);
8779       else
8780         sprintf (buffer, "%s", l + 1);
8781       emitcode ("mov", "%s,%s", buffer,
8782                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8783     }
8784
8785   freeAsmop (right, NULL, ic, TRUE);
8786   freeAsmop (result, NULL, ic, TRUE);
8787 }
8788
8789 /*-----------------------------------------------------------------*/
8790 /* genNearPointerSet - emitcode for near pointer put                */
8791 /*-----------------------------------------------------------------*/
8792 static void
8793 genNearPointerSet (operand * right,
8794                    operand * result,
8795                    iCode * ic)
8796 {
8797   asmop *aop = NULL;
8798   regs *preg = NULL;
8799   char *rname, *l;
8800   sym_link *retype, *letype;
8801   sym_link *ptype = operandType (result);
8802
8803   retype = getSpec (operandType (right));
8804   letype = getSpec (ptype);
8805
8806   aopOp (result, ic, FALSE, FALSE);
8807
8808   /* if the result is rematerializable &
8809      in data space & not a bit variable */
8810   if (AOP_TYPE (result) == AOP_IMMD &&
8811       DCL_TYPE (ptype) == POINTER &&
8812       !IS_BITVAR (retype) &&
8813       !IS_BITVAR (letype))
8814     {
8815       genDataPointerSet (right, result, ic);
8816       return;
8817     }
8818
8819   /* if the value is already in a pointer register
8820      then don't need anything more */
8821   if (!AOP_INPREG (AOP (result)))
8822     {
8823       /* otherwise get a free pointer register */
8824       aop = newAsmop (0);
8825       preg = getFreePtr (ic, &aop, FALSE);
8826       emitcode ("mov", "%s,%s",
8827                 preg->name,
8828                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8829       rname = preg->name;
8830     }
8831   else
8832     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8833
8834   freeAsmop (result, NULL, ic, TRUE);
8835   aopOp (right, ic, FALSE, FALSE);
8836
8837   /* if bitfield then unpack the bits */
8838   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8839     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8840   else
8841     {
8842       /* we have can just get the values */
8843       int size = AOP_SIZE (right);
8844       int offset = 0;
8845
8846       while (size--)
8847         {
8848           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8849           if (*l == '@')
8850             {
8851               MOVA (l);
8852               emitcode ("mov", "@%s,a", rname);
8853             }
8854           else
8855             emitcode ("mov", "@%s,%s", rname, l);
8856           if (size)
8857             emitcode ("inc", "%s", rname);
8858           offset++;
8859         }
8860     }
8861
8862   /* now some housekeeping stuff */
8863   if (aop)
8864     {
8865       /* we had to allocate for this iCode */
8866       freeAsmop (NULL, aop, ic, TRUE);
8867     }
8868   else
8869     {
8870       /* we did not allocate which means left
8871          already in a pointer register, then
8872          if size > 0 && this could be used again
8873          we have to point it back to where it
8874          belongs */
8875       if (AOP_SIZE (right) > 1 &&
8876           !OP_SYMBOL (result)->remat &&
8877           (OP_SYMBOL (result)->liveTo > ic->seq ||
8878            ic->depth))
8879         {
8880           int size = AOP_SIZE (right) - 1;
8881           while (size--)
8882             emitcode ("dec", "%s", rname);
8883         }
8884     }
8885
8886   /* done */
8887   freeAsmop (right, NULL, ic, TRUE);
8888
8889
8890 }
8891
8892 /*-----------------------------------------------------------------*/
8893 /* genPagedPointerSet - emitcode for Paged pointer put             */
8894 /*-----------------------------------------------------------------*/
8895 static void
8896 genPagedPointerSet (operand * right,
8897                     operand * result,
8898                     iCode * ic)
8899 {
8900   asmop *aop = NULL;
8901   regs *preg = NULL;
8902   char *rname, *l;
8903   sym_link *retype, *letype;
8904
8905   retype = getSpec (operandType (right));
8906   letype = getSpec (operandType (result));
8907
8908   aopOp (result, ic, FALSE, FALSE);
8909
8910   /* if the value is already in a pointer register
8911      then don't need anything more */
8912   if (!AOP_INPREG (AOP (result)))
8913     {
8914       /* otherwise get a free pointer register */
8915       aop = newAsmop (0);
8916       preg = getFreePtr (ic, &aop, FALSE);
8917       emitcode ("mov", "%s,%s",
8918                 preg->name,
8919                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8920       rname = preg->name;
8921     }
8922   else
8923     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8924
8925   freeAsmop (result, NULL, ic, TRUE);
8926   aopOp (right, ic, FALSE, FALSE);
8927
8928   /* if bitfield then unpack the bits */
8929   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8930     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8931   else
8932     {
8933       /* we have can just get the values */
8934       int size = AOP_SIZE (right);
8935       int offset = 0;
8936
8937       while (size--)
8938         {
8939           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8940
8941           MOVA (l);
8942           emitcode ("movx", "@%s,a", rname);
8943
8944           if (size)
8945             emitcode ("inc", "%s", rname);
8946
8947           offset++;
8948         }
8949     }
8950
8951   /* now some housekeeping stuff */
8952   if (aop)
8953     {
8954       /* we had to allocate for this iCode */
8955       freeAsmop (NULL, aop, ic, TRUE);
8956     }
8957   else
8958     {
8959       /* we did not allocate which means left
8960          already in a pointer register, then
8961          if size > 0 && this could be used again
8962          we have to point it back to where it
8963          belongs */
8964       if (AOP_SIZE (right) > 1 &&
8965           !OP_SYMBOL (result)->remat &&
8966           (OP_SYMBOL (result)->liveTo > ic->seq ||
8967            ic->depth))
8968         {
8969           int size = AOP_SIZE (right) - 1;
8970           while (size--)
8971             emitcode ("dec", "%s", rname);
8972         }
8973     }
8974
8975   /* done */
8976   freeAsmop (right, NULL, ic, TRUE);
8977
8978
8979 }
8980
8981 /*-----------------------------------------------------------------*/
8982 /* genFarPointerSet - set value from far space                     */
8983 /*-----------------------------------------------------------------*/
8984 static void
8985 genFarPointerSet (operand * right,
8986                   operand * result, iCode * ic)
8987 {
8988   int size, offset;
8989   sym_link *retype = getSpec (operandType (right));
8990   sym_link *letype = getSpec (operandType (result));
8991
8992   aopOp (result, ic, FALSE, FALSE);
8993
8994   /* if the operand is already in dptr
8995      then we do nothing else we move the value to dptr */
8996   if (AOP_TYPE (result) != AOP_STR)
8997     {
8998       /* if this is remateriazable */
8999       if (AOP_TYPE (result) == AOP_IMMD)
9000         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9001       else
9002         {
9003           /* we need to get it byte by byte */
9004           _startLazyDPSEvaluation ();
9005           if (AOP_TYPE (result) != AOP_DPTR)
9006             {
9007               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9008               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9009               if (options.model == MODEL_FLAT24)
9010                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9011             }
9012           else
9013             {
9014               /* We need to generate a load to DPTR indirect through DPTR. */
9015               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9016                 );
9017               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9018               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9019               if (options.model == MODEL_FLAT24)
9020                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9021               emitcode ("pop", "dph");
9022               emitcode ("pop", "dpl");
9023             }
9024           _endLazyDPSEvaluation ();
9025         }
9026     }
9027   /* so dptr know contains the address */
9028   freeAsmop (result, NULL, ic, TRUE);
9029   aopOp (right, ic, FALSE, TRUE);
9030
9031   /* if bit then unpack */
9032   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9033     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9034   else
9035     {
9036       size = AOP_SIZE (right);
9037       offset = 0;
9038
9039       _startLazyDPSEvaluation ();
9040       while (size--)
9041         {
9042           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9043           MOVA (l);
9044
9045           genSetDPTR (0);
9046           _flushLazyDPS ();
9047
9048           emitcode ("movx", "@dptr,a");
9049           if (size)
9050             emitcode ("inc", "dptr");
9051         }
9052       _endLazyDPSEvaluation ();
9053     }
9054
9055   freeAsmop (right, NULL, ic, TRUE);
9056 }
9057
9058 /*-----------------------------------------------------------------*/
9059 /* genGenPointerSet - set value from generic pointer space         */
9060 /*-----------------------------------------------------------------*/
9061 static void
9062 genGenPointerSet (operand * right,
9063                   operand * result, iCode * ic)
9064 {
9065   int size, offset;
9066   sym_link *retype = getSpec (operandType (right));
9067   sym_link *letype = getSpec (operandType (result));
9068
9069   aopOp (result, ic, FALSE, TRUE);
9070
9071   /* if the operand is already in dptr
9072      then we do nothing else we move the value to dptr */
9073   if (AOP_TYPE (result) != AOP_STR)
9074     {
9075       _startLazyDPSEvaluation ();
9076       /* if this is remateriazable */
9077       if (AOP_TYPE (result) == AOP_IMMD)
9078         {
9079           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9080           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9081         }
9082       else
9083         {                       /* we need to get it byte by byte */
9084           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9085           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9086           if (options.model == MODEL_FLAT24) {
9087             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9088             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9089           } else {
9090             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9091           }
9092         }
9093       _endLazyDPSEvaluation ();
9094     }
9095   /* so dptr know contains the address */
9096   freeAsmop (result, NULL, ic, TRUE);
9097   aopOp (right, ic, FALSE, TRUE);
9098
9099   /* if bit then unpack */
9100   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9101     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9102   else
9103     {
9104       size = AOP_SIZE (right);
9105       offset = 0;
9106
9107       _startLazyDPSEvaluation ();
9108       while (size--)
9109         {
9110           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9111           MOVA (l);
9112
9113           genSetDPTR (0);
9114           _flushLazyDPS ();
9115
9116           emitcode ("lcall", "__gptrput");
9117           if (size)
9118             emitcode ("inc", "dptr");
9119         }
9120       _endLazyDPSEvaluation ();
9121     }
9122
9123   freeAsmop (right, NULL, ic, TRUE);
9124 }
9125
9126 /*-----------------------------------------------------------------*/
9127 /* genPointerSet - stores the value into a pointer location        */
9128 /*-----------------------------------------------------------------*/
9129 static void
9130 genPointerSet (iCode * ic)
9131 {
9132   operand *right, *result;
9133   sym_link *type, *etype;
9134   int p_type;
9135
9136   D (emitcode (";", "genPointerSet ");
9137     );
9138
9139   right = IC_RIGHT (ic);
9140   result = IC_RESULT (ic);
9141
9142   /* depending on the type of pointer we need to
9143      move it to the correct pointer register */
9144   type = operandType (result);
9145   etype = getSpec (type);
9146   /* if left is of type of pointer then it is simple */
9147   if (IS_PTR (type) && !IS_FUNC (type->next))
9148     {
9149       p_type = DCL_TYPE (type);
9150     }
9151   else
9152     {
9153       /* we have to go by the storage class */
9154       p_type = PTR_TYPE (SPEC_OCLS (etype));
9155     }
9156
9157   /* now that we have the pointer type we assign
9158      the pointer values */
9159   switch (p_type)
9160     {
9161
9162     case POINTER:
9163     case IPOINTER:
9164       genNearPointerSet (right, result, ic);
9165       break;
9166
9167     case PPOINTER:
9168       genPagedPointerSet (right, result, ic);
9169       break;
9170
9171     case FPOINTER:
9172       genFarPointerSet (right, result, ic);
9173       break;
9174
9175     case GPOINTER:
9176       genGenPointerSet (right, result, ic);
9177       break;
9178     }
9179
9180 }
9181
9182 /*-----------------------------------------------------------------*/
9183 /* genIfx - generate code for Ifx statement                        */
9184 /*-----------------------------------------------------------------*/
9185 static void
9186 genIfx (iCode * ic, iCode * popIc)
9187 {
9188   operand *cond = IC_COND (ic);
9189   int isbit = 0;
9190
9191   D (emitcode (";", "genIfx "););
9192
9193   aopOp (cond, ic, FALSE, FALSE);
9194
9195   /* get the value into acc */
9196   if (AOP_TYPE (cond) != AOP_CRY)
9197     toBoolean (cond);
9198   else
9199     isbit = 1;
9200   /* the result is now in the accumulator */
9201   freeAsmop (cond, NULL, ic, TRUE);
9202
9203   /* if there was something to be popped then do it */
9204   if (popIc)
9205     genIpop (popIc);
9206
9207   /* if the condition is  a bit variable */
9208   if (isbit && IS_ITEMP (cond) &&
9209       SPIL_LOC (cond))
9210     genIfxJump (ic, SPIL_LOC (cond)->rname);
9211   else if (isbit && !IS_ITEMP (cond))
9212     genIfxJump (ic, OP_SYMBOL (cond)->rname);
9213   else
9214     genIfxJump (ic, "a");
9215
9216   ic->generated = 1;
9217 }
9218
9219 /*-----------------------------------------------------------------*/
9220 /* genAddrOf - generates code for address of                       */
9221 /*-----------------------------------------------------------------*/
9222 static void
9223 genAddrOf (iCode * ic)
9224 {
9225   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9226   int size, offset;
9227
9228   D (emitcode (";", "genAddrOf ");
9229     );
9230
9231   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9232
9233   /* if the operand is on the stack then we
9234      need to get the stack offset of this
9235      variable */
9236   if (sym->onStack)
9237     {
9238       /* if it has an offset then we need to compute
9239          it */
9240       if (sym->stack)
9241         {
9242           emitcode ("mov", "a,_bp");
9243           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9244           aopPut (AOP (IC_RESULT (ic)), "a", 0);
9245         }
9246       else
9247         {
9248           /* we can just move _bp */
9249           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9250         }
9251       /* fill the result with zero */
9252       size = AOP_SIZE (IC_RESULT (ic)) - 1;
9253
9254
9255       if (options.stack10bit && size < (FPTRSIZE - 1))
9256         {
9257           fprintf (stderr,
9258                    "*** warning: pointer to stack var truncated.\n");
9259         }
9260
9261       offset = 1;
9262       while (size--)
9263         {
9264           /* Yuck! */
9265           if (options.stack10bit && offset == 2)
9266             {
9267               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9268             }
9269           else
9270             {
9271               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9272             }
9273         }
9274
9275       goto release;
9276     }
9277
9278   /* object not on stack then we need the name */
9279   size = AOP_SIZE (IC_RESULT (ic));
9280   offset = 0;
9281
9282   while (size--)
9283     {
9284       char s[SDCC_NAME_MAX];
9285       if (offset)
9286         sprintf (s, "#(%s >> %d)",
9287                  sym->rname,
9288                  offset * 8);
9289       else
9290         sprintf (s, "#%s", sym->rname);
9291       aopPut (AOP (IC_RESULT (ic)), s, offset++);
9292     }
9293
9294 release:
9295   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9296
9297 }
9298
9299 /*-----------------------------------------------------------------*/
9300 /* genArrayInit - generates code for address of                       */
9301 /*-----------------------------------------------------------------*/
9302 static void
9303 genArrayInit (iCode * ic)
9304 {
9305     literalList *iLoop;
9306     int         ix, count;
9307     int         elementSize = 0, eIndex;
9308     unsigned    val, lastVal;
9309     sym_link    *type;
9310     operand     *left=IC_LEFT(ic);
9311     
9312     D (emitcode (";", "genArrayInit "););
9313
9314     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9315     
9316     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9317     {
9318         // Load immediate value into DPTR.
9319         emitcode("mov", "dptr, %s",
9320              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9321     }
9322     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9323     {
9324 #if 0
9325       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9326               "Unexpected operand to genArrayInit.\n");
9327       exit(1);
9328 #else
9329       // a regression because of SDCCcse.c:1.52
9330       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9331       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9332       if (options.model == MODEL_FLAT24)
9333         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9334 #endif
9335     }
9336     
9337     type = operandType(IC_LEFT(ic));
9338     
9339     if (type && type->next)
9340     {
9341         elementSize = getSize(type->next);
9342     }
9343     else
9344     {
9345         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9346                                 "can't determine element size in genArrayInit.\n");
9347         exit(1);
9348     }
9349     
9350     iLoop = IC_ARRAYILIST(ic);
9351     lastVal = 0xffff;
9352     
9353     while (iLoop)
9354     {
9355         bool firstpass = TRUE;
9356         
9357         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
9358                  iLoop->count, (int)iLoop->literalValue, elementSize);
9359         
9360         ix = iLoop->count;
9361         
9362         while (ix)
9363         {
9364             symbol *tlbl = NULL;
9365             
9366             count = ix > 256 ? 256 : ix;
9367             
9368             if (count > 1)
9369             {
9370                 tlbl = newiTempLabel (NULL);
9371                 if (firstpass || (count & 0xff))
9372                 {
9373                     emitcode("mov", "b, #0x%x", count & 0xff);
9374                 }
9375                 
9376                 emitcode ("", "%05d$:", tlbl->key + 100);
9377             }
9378             
9379             firstpass = FALSE;
9380                 
9381             for (eIndex = 0; eIndex < elementSize; eIndex++)
9382             {
9383                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9384                 if (val != lastVal)
9385                 {
9386                     emitcode("mov", "a, #0x%x", val);
9387                     lastVal = val;
9388                 }
9389                 
9390                 emitcode("movx", "@dptr, a");
9391                 emitcode("inc", "dptr");
9392             }
9393             
9394             if (count > 1)
9395             {
9396                 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9397             }
9398             
9399             ix -= count;
9400         }
9401         
9402         iLoop = iLoop->next;
9403     }
9404     
9405     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9406 }
9407
9408 /*-----------------------------------------------------------------*/
9409 /* genFarFarAssign - assignment when both are in far space         */
9410 /*-----------------------------------------------------------------*/
9411 static void
9412 genFarFarAssign (operand * result, operand * right, iCode * ic)
9413 {
9414   int size = AOP_SIZE (right);
9415   int offset = 0;
9416   symbol *rSym = NULL;
9417
9418   if (size == 1)
9419   {
9420       /* quick & easy case. */
9421       D(emitcode(";","genFarFarAssign (1 byte case)"););      
9422       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9423       freeAsmop (right, NULL, ic, FALSE);
9424       /* now assign DPTR to result */
9425       _G.accInUse++;
9426       aopOp(result, ic, FALSE, FALSE);
9427       _G.accInUse--;
9428       aopPut(AOP(result), "a", 0);
9429       freeAsmop(result, NULL, ic, FALSE);
9430       return;
9431   }
9432   
9433   /* See if we've got an underlying symbol to abuse. */
9434   if (IS_SYMOP(result) && OP_SYMBOL(result))
9435   {
9436       if (IS_TRUE_SYMOP(result))
9437       {
9438           rSym = OP_SYMBOL(result);
9439       }
9440       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9441       {
9442           rSym = OP_SYMBOL(result)->usl.spillLoc;
9443       }
9444   }
9445              
9446   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9447   {
9448       /* We can use the '390 auto-toggle feature to good effect here. */
9449       
9450       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9451       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
9452       emitcode ("mov", "dptr,#%s", rSym->rname); 
9453       /* DP2 = result, DP1 = right, DP1 is current. */
9454       while (size)
9455       {
9456           emitcode("movx", "a,@dptr");
9457           emitcode("movx", "@dptr,a");
9458           if (--size)
9459           {
9460                emitcode("inc", "dptr");
9461                emitcode("inc", "dptr");
9462           }
9463       }
9464       emitcode("mov", "dps, #0");
9465       freeAsmop (right, NULL, ic, FALSE);
9466 #if 0
9467 some alternative code for processors without auto-toggle
9468 no time to test now, so later well put in...kpb
9469         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9470         emitcode("mov", "dps, #0x01");  /* Select DPTR2. */
9471         emitcode ("mov", "dptr,#%s", rSym->rname); 
9472         /* DP2 = result, DP1 = right, DP1 is current. */
9473         while (size)
9474         {
9475           --size;
9476           emitcode("movx", "a,@dptr");
9477           if (size)
9478             emitcode("inc", "dptr");
9479           emitcode("inc", "dps");
9480           emitcode("movx", "@dptr,a");
9481           if (size)
9482             emitcode("inc", "dptr");
9483           emitcode("inc", "dps");
9484         }
9485         emitcode("mov", "dps, #0");
9486         freeAsmop (right, NULL, ic, FALSE);
9487 #endif
9488   }
9489   else
9490   {
9491       D (emitcode (";", "genFarFarAssign"););
9492       aopOp (result, ic, TRUE, TRUE);
9493
9494       _startLazyDPSEvaluation ();
9495       
9496       while (size--)
9497         {
9498           aopPut (AOP (result),
9499                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9500           offset++;
9501         }
9502       _endLazyDPSEvaluation ();
9503       freeAsmop (result, NULL, ic, FALSE);
9504       freeAsmop (right, NULL, ic, FALSE);
9505   }
9506 }
9507
9508 /*-----------------------------------------------------------------*/
9509 /* genAssign - generate code for assignment                        */
9510 /*-----------------------------------------------------------------*/
9511 static void
9512 genAssign (iCode * ic)
9513 {
9514   operand *result, *right;
9515   int size, offset;
9516   unsigned long lit = 0L;
9517
9518   D (emitcode (";", "genAssign ");
9519     );
9520
9521   result = IC_RESULT (ic);
9522   right = IC_RIGHT (ic);
9523
9524   /* if they are the same */
9525   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9526     return;
9527
9528   aopOp (right, ic, FALSE, FALSE);
9529
9530   emitcode (";", "genAssign: resultIsFar = %s",
9531             isOperandInFarSpace (result) ?
9532             "TRUE" : "FALSE");
9533
9534   /* special case both in far space */
9535   if ((AOP_TYPE (right) == AOP_DPTR ||
9536        AOP_TYPE (right) == AOP_DPTR2) &&
9537   /* IS_TRUE_SYMOP(result)       && */
9538       isOperandInFarSpace (result))
9539     {
9540       genFarFarAssign (result, right, ic);
9541       return;
9542     }
9543
9544   aopOp (result, ic, TRUE, FALSE);
9545
9546   /* if they are the same registers */
9547   if (sameRegs (AOP (right), AOP (result)))
9548     goto release;
9549
9550   /* if the result is a bit */
9551   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9552     {
9553       /* if the right size is a literal then
9554          we know what the value is */
9555       if (AOP_TYPE (right) == AOP_LIT)
9556         {
9557           if (((int) operandLitValue (right)))
9558             aopPut (AOP (result), one, 0);
9559           else
9560             aopPut (AOP (result), zero, 0);
9561           goto release;
9562         }
9563
9564       /* the right is also a bit variable */
9565       if (AOP_TYPE (right) == AOP_CRY)
9566         {
9567           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9568           aopPut (AOP (result), "c", 0);
9569           goto release;
9570         }
9571
9572       /* we need to or */
9573       toBoolean (right);
9574       aopPut (AOP (result), "a", 0);
9575       goto release;
9576     }
9577
9578   /* bit variables done */
9579   /* general case */
9580   size = AOP_SIZE (result);
9581   offset = 0;
9582   if (AOP_TYPE (right) == AOP_LIT)
9583     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9584
9585   if ((size > 1) &&
9586       (AOP_TYPE (result) != AOP_REG) &&
9587       (AOP_TYPE (right) == AOP_LIT) &&
9588       !IS_FLOAT (operandType (right)))
9589     {
9590       _startLazyDPSEvaluation ();
9591       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9592         {
9593           aopPut (AOP (result),
9594                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9595                   offset);
9596           offset++;
9597           size--;
9598         }
9599       /* And now fill the rest with zeros. */
9600       if (size)
9601         {
9602           emitcode ("clr", "a");
9603         }
9604       while (size--)
9605         {
9606           aopPut (AOP (result), "a", offset++);
9607         }
9608       _endLazyDPSEvaluation ();
9609     }
9610   else
9611     {
9612       _startLazyDPSEvaluation ();
9613       while (size--)
9614         {
9615           aopPut (AOP (result),
9616                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9617                   offset);
9618           offset++;
9619         }
9620       _endLazyDPSEvaluation ();
9621     }
9622
9623 release:
9624   freeAsmop (right, NULL, ic, FALSE);
9625   freeAsmop (result, NULL, ic, TRUE);
9626 }
9627
9628 /*-----------------------------------------------------------------*/
9629 /* genJumpTab - generates code for jump table                      */
9630 /*-----------------------------------------------------------------*/
9631 static void
9632 genJumpTab (iCode * ic)
9633 {
9634   symbol *jtab;
9635   char *l;
9636
9637   D (emitcode (";", "genJumpTab ");
9638     );
9639
9640   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9641   /* get the condition into accumulator */
9642   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9643   MOVA (l);
9644   /* multiply by four! */
9645   emitcode ("add", "a,acc");
9646   emitcode ("add", "a,acc");
9647   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9648
9649   jtab = newiTempLabel (NULL);
9650   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9651   emitcode ("jmp", "@a+dptr");
9652   emitcode ("", "%05d$:", jtab->key + 100);
9653   /* now generate the jump labels */
9654   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9655        jtab = setNextItem (IC_JTLABELS (ic)))
9656     emitcode ("ljmp", "%05d$", jtab->key + 100);
9657
9658 }
9659
9660 /*-----------------------------------------------------------------*/
9661 /* genCast - gen code for casting                                  */
9662 /*-----------------------------------------------------------------*/
9663 static void
9664 genCast (iCode * ic)
9665 {
9666   operand *result = IC_RESULT (ic);
9667   sym_link *ctype = operandType (IC_LEFT (ic));
9668   sym_link *rtype = operandType (IC_RIGHT (ic));
9669   operand *right = IC_RIGHT (ic);
9670   int size, offset;
9671
9672   D (emitcode (";", "genCast ");
9673     );
9674
9675   /* if they are equivalent then do nothing */
9676   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9677     return;
9678
9679   aopOp (right, ic, FALSE, FALSE);
9680   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9681
9682   /* if the result is a bit */
9683   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9684   if (IS_BITVAR(OP_SYMBOL(result)->type))
9685     {
9686       /* if the right size is a literal then
9687          we know what the value is */
9688       if (AOP_TYPE (right) == AOP_LIT)
9689         {
9690           if (((int) operandLitValue (right)))
9691             aopPut (AOP (result), one, 0);
9692           else
9693             aopPut (AOP (result), zero, 0);
9694
9695           goto release;
9696         }
9697
9698       /* the right is also a bit variable */
9699       if (AOP_TYPE (right) == AOP_CRY)
9700         {
9701           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9702           aopPut (AOP (result), "c", 0);
9703           goto release;
9704         }
9705
9706       /* we need to or */
9707       toBoolean (right);
9708       aopPut (AOP (result), "a", 0);
9709       goto release;
9710     }
9711
9712   /* if they are the same size : or less */
9713   if (AOP_SIZE (result) <= AOP_SIZE (right))
9714     {
9715
9716       /* if they are in the same place */
9717       if (sameRegs (AOP (right), AOP (result)))
9718         goto release;
9719
9720       /* if they in different places then copy */
9721       size = AOP_SIZE (result);
9722       offset = 0;
9723       _startLazyDPSEvaluation ();
9724       while (size--)
9725         {
9726           aopPut (AOP (result),
9727                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9728                   offset);
9729           offset++;
9730         }
9731       _endLazyDPSEvaluation ();
9732       goto release;
9733     }
9734
9735
9736   /* if the result is of type pointer */
9737   if (IS_PTR (ctype))
9738     {
9739
9740       int p_type;
9741       sym_link *type = operandType (right);
9742
9743       /* pointer to generic pointer */
9744       if (IS_GENPTR (ctype))
9745         {
9746           char *l = zero;
9747
9748           if (IS_PTR (type))
9749             {
9750               p_type = DCL_TYPE (type);
9751             }
9752           else
9753             {
9754 #if OLD_CAST_BEHAVIOR
9755               /* KV: we are converting a non-pointer type to
9756                * a generic pointer. This (ifdef'd out) code
9757                * says that the resulting generic pointer
9758                * should have the same class as the storage
9759                * location of the non-pointer variable.
9760                *
9761                * For example, converting an int (which happens
9762                * to be stored in DATA space) to a pointer results
9763                * in a DATA generic pointer; if the original int
9764                * in XDATA space, so will be the resulting pointer.
9765                *
9766                * I don't like that behavior, and thus this change:
9767                * all such conversions will be forced to XDATA and
9768                * throw a warning. If you want some non-XDATA
9769                * type, or you want to suppress the warning, you
9770                * must go through an intermediate cast, like so:
9771                *
9772                * char _generic *gp = (char _xdata *)(intVar);
9773                */
9774               sym_link *etype = getSpec (type);
9775
9776               /* we have to go by the storage class */
9777               if (SPEC_OCLS (etype) != generic)
9778                 {
9779                   p_type = PTR_TYPE (SPEC_OCLS (etype));
9780                 }
9781               else
9782 #endif
9783                 {
9784                   /* Converting unknown class (i.e. register variable)
9785                    * to generic pointer. This is not good, but
9786                    * we'll make a guess (and throw a warning).
9787                    */
9788                   p_type = FPOINTER;
9789                   werror (W_INT_TO_GEN_PTR_CAST);
9790                 }
9791             }
9792
9793           /* the first two bytes are known */
9794           size = GPTRSIZE - 1;
9795           offset = 0;
9796           _startLazyDPSEvaluation ();
9797           while (size--)
9798             {
9799               aopPut (AOP (result),
9800                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9801                       offset);
9802               offset++;
9803             }
9804           _endLazyDPSEvaluation ();
9805
9806           /* the last byte depending on type */
9807           switch (p_type)
9808             {
9809             case IPOINTER:
9810             case POINTER:
9811               l = zero;
9812               break;
9813             case FPOINTER:
9814               l = one;
9815               break;
9816             case CPOINTER:
9817               l = "#0x02";
9818               break;
9819             case PPOINTER:
9820               l = "#0x03";
9821               break;
9822
9823             default:
9824               /* this should never happen */
9825               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9826                       "got unknown pointer type");
9827               exit (1);
9828             }
9829           aopPut (AOP (result), l, GPTRSIZE - 1);
9830           goto release;
9831         }
9832
9833       /* just copy the pointers */
9834       size = AOP_SIZE (result);
9835       offset = 0;
9836       _startLazyDPSEvaluation ();
9837       while (size--)
9838         {
9839           aopPut (AOP (result),
9840                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9841                   offset);
9842           offset++;
9843         }
9844       _endLazyDPSEvaluation ();
9845       goto release;
9846     }
9847
9848   /* so we now know that the size of destination is greater
9849      than the size of the source */
9850   /* we move to result for the size of source */
9851   size = AOP_SIZE (right);
9852   offset = 0;
9853   _startLazyDPSEvaluation ();
9854   while (size--)
9855     {
9856       aopPut (AOP (result),
9857               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9858               offset);
9859       offset++;
9860     }
9861   _endLazyDPSEvaluation ();
9862
9863   /* now depending on the sign of the source && destination */
9864   size = AOP_SIZE (result) - AOP_SIZE (right);
9865   /* if unsigned or not an integral type */
9866   /* also, if the source is a bit, we don't need to sign extend, because
9867    * it can't possibly have set the sign bit.
9868    */
9869   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9870     {
9871       while (size--)
9872         {
9873           aopPut (AOP (result), zero, offset++);
9874         }
9875     }
9876   else
9877     {
9878       /* we need to extend the sign :{ */
9879       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9880                         FALSE, FALSE, TRUE);
9881       MOVA (l);
9882       emitcode ("rlc", "a");
9883       emitcode ("subb", "a,acc");
9884       while (size--)
9885         aopPut (AOP (result), "a", offset++);
9886     }
9887
9888   /* we are done hurray !!!! */
9889
9890 release:
9891   freeAsmop (right, NULL, ic, TRUE);
9892   freeAsmop (result, NULL, ic, TRUE);
9893
9894 }
9895
9896 /*-----------------------------------------------------------------*/
9897 /* genDjnz - generate decrement & jump if not zero instrucion      */
9898 /*-----------------------------------------------------------------*/
9899 static int
9900 genDjnz (iCode * ic, iCode * ifx)
9901 {
9902   symbol *lbl, *lbl1;
9903   if (!ifx)
9904     return 0;
9905
9906   /* if the if condition has a false label
9907      then we cannot save */
9908   if (IC_FALSE (ifx))
9909     return 0;
9910
9911   /* if the minus is not of the form
9912      a = a - 1 */
9913   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9914       !IS_OP_LITERAL (IC_RIGHT (ic)))
9915     return 0;
9916
9917   if (operandLitValue (IC_RIGHT (ic)) != 1)
9918     return 0;
9919
9920   /* if the size of this greater than one then no
9921      saving */
9922   if (getSize (operandType (IC_RESULT (ic))) > 1)
9923     return 0;
9924
9925   /* otherwise we can save BIG */
9926   D(emitcode(";", "genDjnz"););
9927
9928   lbl = newiTempLabel (NULL);
9929   lbl1 = newiTempLabel (NULL);
9930
9931   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9932
9933   if (AOP_NEEDSACC(IC_RESULT(ic)))
9934   {
9935       /* If the result is accessed indirectly via
9936        * the accumulator, we must explicitly write
9937        * it back after the decrement.
9938        */
9939       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9940       
9941       if (strcmp(rByte, "a"))
9942       {
9943            /* Something is hopelessly wrong */
9944            fprintf(stderr, "*** warning: internal error at %s:%d\n",
9945                    __FILE__, __LINE__);
9946            /* We can just give up; the generated code will be inefficient,
9947             * but what the hey.
9948             */
9949            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9950            return 0;
9951       }
9952       emitcode ("dec", "%s", rByte);
9953       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9954       emitcode ("jnz", "%05d$", lbl->key + 100);
9955   }
9956   else if (IS_AOP_PREG (IC_RESULT (ic)))
9957     {
9958       emitcode ("dec", "%s",
9959                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9960       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9961       emitcode ("jnz", "%05d$", lbl->key + 100);
9962     }
9963   else
9964     {
9965       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9966                 lbl->key + 100);
9967     }
9968   emitcode ("sjmp", "%05d$", lbl1->key + 100);
9969   emitcode ("", "%05d$:", lbl->key + 100);
9970   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9971   emitcode ("", "%05d$:", lbl1->key + 100);
9972
9973   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9974   ifx->generated = 1;
9975   return 1;
9976 }
9977
9978 /*-----------------------------------------------------------------*/
9979 /* genReceive - generate code for a receive iCode                  */
9980 /*-----------------------------------------------------------------*/
9981 static void
9982 genReceive (iCode * ic)
9983 {
9984
9985   D (emitcode (";", "genReceive ");
9986     );
9987
9988   if (isOperandInFarSpace (IC_RESULT (ic)) &&
9989       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9990        IS_TRUE_SYMOP (IC_RESULT (ic))))
9991     {
9992       int size = getSize (operandType (IC_RESULT (ic)));
9993       int offset = fReturnSizeDS390 - size;
9994       while (size--)
9995         {
9996           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
9997                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
9998           offset++;
9999         }
10000       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10001       size = AOP_SIZE (IC_RESULT (ic));
10002       offset = 0;
10003       while (size--)
10004         {
10005           emitcode ("pop", "acc");
10006           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10007         }
10008
10009     }
10010   else
10011     {
10012       _G.accInUse++;
10013       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10014       _G.accInUse--;
10015       assignResultValue (IC_RESULT (ic));
10016     }
10017
10018   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10019 }
10020
10021 /*-----------------------------------------------------------------*/
10022 /* gen390Code - generate code for Dallas 390 based controllers     */
10023 /*-----------------------------------------------------------------*/
10024 void
10025 gen390Code (iCode * lic)
10026 {
10027   iCode *ic;
10028   int cln = 0;
10029
10030   lineHead = lineCurr = NULL;
10031
10032   if (options.model == MODEL_FLAT24) {
10033     fReturnSizeDS390 = 5;
10034     fReturn = fReturn24;
10035   } else {
10036     fReturnSizeDS390 = 4;
10037     fReturn = fReturn16;
10038     options.stack10bit=0;
10039   }
10040 #if 0
10041   //REMOVE ME!!!
10042   /* print the allocation information */
10043   if (allocInfo)
10044     printAllocInfo (currFunc, codeOutFile);
10045 #endif
10046   /* if debug information required */
10047   if (options.debug && currFunc)
10048     {
10049       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10050       _G.debugLine = 1;
10051       if (IS_STATIC (currFunc->etype))
10052         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10053       else
10054         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10055       _G.debugLine = 0;
10056     }
10057   /* stack pointer name */
10058   if (options.useXstack)
10059     spname = "_spx";
10060   else
10061     spname = "sp";
10062
10063
10064   for (ic = lic; ic; ic = ic->next)
10065     {
10066
10067       if (cln != ic->lineno)
10068         {
10069           if (options.debug)
10070             {
10071               _G.debugLine = 1;
10072               emitcode ("", "C$%s$%d$%d$%d ==.",
10073                         FileBaseName (ic->filename), ic->lineno,
10074                         ic->level, ic->block);
10075               _G.debugLine = 0;
10076             }
10077           emitcode (";", "%s %d", ic->filename, ic->lineno);
10078           cln = ic->lineno;
10079         }
10080       /* if the result is marked as
10081          spilt and rematerializable or code for
10082          this has already been generated then
10083          do nothing */
10084       if (resultRemat (ic) || ic->generated)
10085         continue;
10086
10087       /* depending on the operation */
10088       switch (ic->op)
10089         {
10090         case '!':
10091           genNot (ic);
10092           break;
10093
10094         case '~':
10095           genCpl (ic);
10096           break;
10097
10098         case UNARYMINUS:
10099           genUminus (ic);
10100           break;
10101
10102         case IPUSH:
10103           genIpush (ic);
10104           break;
10105
10106         case IPOP:
10107           /* IPOP happens only when trying to restore a
10108              spilt live range, if there is an ifx statement
10109              following this pop then the if statement might
10110              be using some of the registers being popped which
10111              would destory the contents of the register so
10112              we need to check for this condition and handle it */
10113           if (ic->next &&
10114               ic->next->op == IFX &&
10115               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10116             genIfx (ic->next, ic);
10117           else
10118             genIpop (ic);
10119           break;
10120
10121         case CALL:
10122           genCall (ic);
10123           break;
10124
10125         case PCALL:
10126           genPcall (ic);
10127           break;
10128
10129         case FUNCTION:
10130           genFunction (ic);
10131           break;
10132
10133         case ENDFUNCTION:
10134           genEndFunction (ic);
10135           break;
10136
10137         case RETURN:
10138           genRet (ic);
10139           break;
10140
10141         case LABEL:
10142           genLabel (ic);
10143           break;
10144
10145         case GOTO:
10146           genGoto (ic);
10147           break;
10148
10149         case '+':
10150           genPlus (ic);
10151           break;
10152
10153         case '-':
10154           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10155             genMinus (ic);
10156           break;
10157
10158         case '*':
10159           genMult (ic);
10160           break;
10161
10162         case '/':
10163           genDiv (ic);
10164           break;
10165
10166         case '%':
10167           genMod (ic);
10168           break;
10169
10170         case '>':
10171           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10172           break;
10173
10174         case '<':
10175           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10176           break;
10177
10178         case LE_OP:
10179         case GE_OP:
10180         case NE_OP:
10181
10182           /* note these two are xlated by algebraic equivalence
10183              during parsing SDCC.y */
10184           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10185                   "got '>=' or '<=' shouldn't have come here");
10186           break;
10187
10188         case EQ_OP:
10189           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10190           break;
10191
10192         case AND_OP:
10193           genAndOp (ic);
10194           break;
10195
10196         case OR_OP:
10197           genOrOp (ic);
10198           break;
10199
10200         case '^':
10201           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10202           break;
10203
10204         case '|':
10205           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10206           break;
10207
10208         case BITWISEAND:
10209           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10210           break;
10211
10212         case INLINEASM:
10213           genInline (ic);
10214           break;
10215
10216         case RRC:
10217           genRRC (ic);
10218           break;
10219
10220         case RLC:
10221           genRLC (ic);
10222           break;
10223
10224         case GETHBIT:
10225           genGetHbit (ic);
10226           break;
10227
10228         case LEFT_OP:
10229           genLeftShift (ic);
10230           break;
10231
10232         case RIGHT_OP:
10233           genRightShift (ic);
10234           break;
10235
10236         case GET_VALUE_AT_ADDRESS:
10237           genPointerGet (ic);
10238           break;
10239
10240         case '=':
10241           if (POINTER_SET (ic))
10242             genPointerSet (ic);
10243           else
10244             genAssign (ic);
10245           break;
10246
10247         case IFX:
10248           genIfx (ic, NULL);
10249           break;
10250
10251         case ADDRESS_OF:
10252           genAddrOf (ic);
10253           break;
10254
10255         case JUMPTABLE:
10256           genJumpTab (ic);
10257           break;
10258
10259         case CAST:
10260           genCast (ic);
10261           break;
10262
10263         case RECEIVE:
10264           genReceive (ic);
10265           break;
10266
10267         case SEND:
10268           addSet (&_G.sendSet, ic);
10269           break;
10270
10271         case ARRAYINIT:
10272             genArrayInit(ic);
10273             break;
10274             
10275         default:
10276           ic = ic;
10277         }
10278     }
10279
10280
10281   /* now we are ready to call the
10282      peep hole optimizer */
10283   if (!options.nopeep)
10284     peepHole (&lineHead);
10285
10286   /* now do the actual printing */
10287   printLine (lineHead, codeOutFile);
10288   return;
10289 }