fix broken genOr
[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 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3362       // Please don't bring it back without a really good reason.
3363 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3364 // (because all three operands are in far space).
3365 #define AOP_OP_3(ic) \
3366     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3367     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3368     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3369               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3370     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3371         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3372     { \
3373         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3374         fprintf(stderr,                                  \
3375                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3376     }
3377 #endif
3378
3379 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3380 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3381 // will be set TRUE. The caller must then handle the case specially, noting
3382 // that the IC_RESULT operand is not aopOp'd.
3383 #define AOP_OP_3_NOFATAL(ic, rc) \
3384     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3385     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3386     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3387         isOperandInFarSpace(IC_RESULT(ic))) \
3388     { \
3389        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3390        rc = TRUE; \
3391     }  \
3392     else \
3393     { \
3394        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3395                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3396        rc = FALSE; \
3397        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3398            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3399        { \
3400             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3401             fprintf(stderr,                                  \
3402                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3403        } \
3404     }
3405
3406 // aopOp the left & right operands of an ic.
3407 #define AOP_OP_2(ic) \
3408     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3409     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3410
3411 // convienience macro.
3412 #define AOP_SET_LOCALS(ic) \
3413     left = IC_LEFT(ic); \
3414     right = IC_RIGHT(ic); \
3415     result = IC_RESULT(ic);
3416
3417
3418 // Given an integer value of pushedSize bytes on the stack,
3419 // adjust it to be resultSize bytes, either by discarding
3420 // the most significant bytes or by zero-padding.
3421 //
3422 // On exit from this macro, pushedSize will have been adjusted to
3423 // equal resultSize, and ACC may be trashed.
3424 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3425       /* If the pushed data is bigger than the result,          \
3426        * simply discard unused bytes. Icky, but works.          \
3427        */                                                       \
3428       while (pushedSize > resultSize)                           \
3429       {                                                         \
3430           D (emitcode (";", "discarding unused result byte."););\
3431           emitcode ("pop", "acc");                              \
3432           pushedSize--;                                         \
3433       }                                                         \
3434       if (pushedSize < resultSize)                              \
3435       {                                                         \
3436           emitcode ("clr", "a");                                \
3437           /* Conversly, we haven't pushed enough here.          \
3438            * just zero-pad, and all is well.                    \
3439            */                                                   \
3440           while (pushedSize < resultSize)                       \
3441           {                                                     \
3442               emitcode("push", "acc");                          \
3443               pushedSize++;                                     \
3444           }                                                     \
3445       }                                                         \
3446       assert(pushedSize == resultSize);
3447
3448 /*-----------------------------------------------------------------*/
3449 /* genPlus - generates code for addition                           */
3450 /*-----------------------------------------------------------------*/
3451 static void
3452 genPlus (iCode * ic)
3453 {
3454   int size, offset = 0;
3455   bool pushResult = FALSE;
3456   int rSize;
3457
3458   D (emitcode (";", "genPlus "););
3459
3460   /* special cases :- */
3461
3462   AOP_OP_3_NOFATAL (ic, pushResult);
3463   if (pushResult)
3464     {
3465       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3466     }
3467
3468   if (!pushResult)
3469     {
3470       /* if literal, literal on the right or
3471          if left requires ACC or right is already
3472          in ACC */
3473       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3474        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3475           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3476         {
3477           operand *t = IC_RIGHT (ic);
3478           IC_RIGHT (ic) = IC_LEFT (ic);
3479           IC_LEFT (ic) = t;
3480           emitcode (";", "Swapped plus args.");
3481         }
3482
3483       /* if both left & right are in bit
3484          space */
3485       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3486           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3487         {
3488           genPlusBits (ic);
3489           goto release;
3490         }
3491
3492       /* if left in bit space & right literal */
3493       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3494           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3495         {
3496           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3497           /* if result in bit space */
3498           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3499             {
3500               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3501                 emitcode ("cpl", "c");
3502               outBitC (IC_RESULT (ic));
3503             }
3504           else
3505             {
3506               size = getDataSize (IC_RESULT (ic));
3507               _startLazyDPSEvaluation ();
3508               while (size--)
3509                 {
3510                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3511                   emitcode ("addc", "a,#00");
3512                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3513                 }
3514               _endLazyDPSEvaluation ();
3515             }
3516           goto release;
3517         }
3518
3519       /* if I can do an increment instead
3520          of add then GOOD for ME */
3521       if (genPlusIncr (ic) == TRUE)
3522         {
3523           emitcode (";", "did genPlusIncr");
3524           goto release;
3525         }
3526
3527     }
3528   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3529
3530   _startLazyDPSEvaluation ();
3531   while (size--)
3532     {
3533       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3534         {
3535           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3536           if (offset == 0)
3537             emitcode ("add", "a,%s",
3538                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3539           else
3540             emitcode ("addc", "a,%s",
3541                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3542         }
3543       else
3544         {
3545           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3546           {
3547               /* right is going to use ACC or we would have taken the
3548                * above branch.
3549                */
3550               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3551        TR_AP("#3");
3552               D(emitcode(";", "+ AOP_ACC special case."););
3553               emitcode("xch", "a, %s", DP2_RESULT_REG);
3554           }
3555           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3556           if (offset == 0)
3557           {
3558             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3559             {
3560          TR_AP("#4");
3561                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3562             }
3563             else
3564             {
3565                 emitcode ("add", "a,%s",
3566                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3567             }
3568           }
3569           else
3570           {
3571             emitcode ("addc", "a,%s",
3572                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3573           }
3574         }
3575       if (!pushResult)
3576         {
3577           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3578         }
3579       else
3580         {
3581           emitcode ("push", "acc");
3582         }
3583       offset++;
3584     }
3585   _endLazyDPSEvaluation ();
3586
3587   if (pushResult)
3588     {
3589       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3590
3591       size = getDataSize (IC_LEFT (ic));
3592       rSize = getDataSize (IC_RESULT (ic));
3593
3594       ADJUST_PUSHED_RESULT(size, rSize);
3595
3596       _startLazyDPSEvaluation ();
3597       while (size--)
3598         {
3599           emitcode ("pop", "acc");
3600           aopPut (AOP (IC_RESULT (ic)), "a", size);
3601         }
3602       _endLazyDPSEvaluation ();
3603     }
3604
3605   adjustArithmeticResult (ic);
3606
3607 release:
3608   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3609   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3610   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3611 }
3612
3613 /*-----------------------------------------------------------------*/
3614 /* genMinusDec :- does subtraction with deccrement if possible     */
3615 /*-----------------------------------------------------------------*/
3616 static bool
3617 genMinusDec (iCode * ic)
3618 {
3619   unsigned int icount;
3620   unsigned int size = getDataSize (IC_RESULT (ic));
3621
3622   /* will try to generate an increment */
3623   /* if the right side is not a literal
3624      we cannot */
3625   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3626     return FALSE;
3627
3628   /* if the literal value of the right hand side
3629      is greater than 4 then it is not worth it */
3630   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3631     return FALSE;
3632
3633   /* if decrement 16 bits in register */
3634   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3635       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3636       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3637       (size > 1) &&
3638       (icount == 1))
3639     {
3640       symbol *tlbl;
3641       int emitTlbl;
3642       int labelRange;
3643
3644       /* If the next instruction is a goto and the goto target
3645          * is <= 5 instructions previous to this, we can generate
3646          * jumps straight to that target.
3647        */
3648       if (ic->next && ic->next->op == GOTO
3649           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3650           && labelRange <= 5)
3651         {
3652           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3653           tlbl = IC_LABEL (ic->next);
3654           emitTlbl = 0;
3655         }
3656       else
3657         {
3658           tlbl = newiTempLabel (NULL);
3659           emitTlbl = 1;
3660         }
3661
3662       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3663       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3664           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3665           IS_AOP_PREG (IC_RESULT (ic)))
3666         emitcode ("cjne", "%s,#0xff,%05d$"
3667                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3668                   ,tlbl->key + 100);
3669       else
3670         {
3671           emitcode ("mov", "a,#0xff");
3672           emitcode ("cjne", "a,%s,%05d$"
3673                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3674                     ,tlbl->key + 100);
3675         }
3676       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3677       if (size > 2)
3678         {
3679           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3680               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3681               IS_AOP_PREG (IC_RESULT (ic)))
3682             emitcode ("cjne", "%s,#0xff,%05d$"
3683                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3684                       ,tlbl->key + 100);
3685           else
3686             {
3687               emitcode ("cjne", "a,%s,%05d$"
3688                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3689                         ,tlbl->key + 100);
3690             }
3691           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3692         }
3693       if (size > 3)
3694         {
3695           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3696               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3697               IS_AOP_PREG (IC_RESULT (ic)))
3698             emitcode ("cjne", "%s,#0xff,%05d$"
3699                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3700                       ,tlbl->key + 100);
3701           else
3702             {
3703               emitcode ("cjne", "a,%s,%05d$"
3704                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3705                         ,tlbl->key + 100);
3706             }
3707           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3708         }
3709       if (emitTlbl)
3710         {
3711           emitcode ("", "%05d$:", tlbl->key + 100);
3712         }
3713       return TRUE;
3714     }
3715
3716   /* if the sizes are greater than 1 then we cannot */
3717   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3718       AOP_SIZE (IC_LEFT (ic)) > 1)
3719     return FALSE;
3720
3721   /* we can if the aops of the left & result match or
3722      if they are in registers and the registers are the
3723      same */
3724   if (
3725        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3726        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3727        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3728     {
3729
3730       _startLazyDPSEvaluation ();
3731       while (icount--)
3732         {
3733           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3734         }
3735       _endLazyDPSEvaluation ();
3736
3737       return TRUE;
3738     }
3739
3740   return FALSE;
3741 }
3742
3743 /*-----------------------------------------------------------------*/
3744 /* addSign - complete with sign                                    */
3745 /*-----------------------------------------------------------------*/
3746 static void
3747 addSign (operand * result, int offset, int sign)
3748 {
3749   int size = (getDataSize (result) - offset);
3750   if (size > 0)
3751     {
3752       _startLazyDPSEvaluation();
3753       if (sign)
3754         {
3755           emitcode ("rlc", "a");
3756           emitcode ("subb", "a,acc");
3757           while (size--)
3758           {
3759             aopPut (AOP (result), "a", offset++);
3760           }
3761         }
3762       else
3763       {
3764         while (size--)
3765         {
3766           aopPut (AOP (result), zero, offset++);
3767         }
3768       }
3769       _endLazyDPSEvaluation();
3770     }
3771 }
3772
3773 /*-----------------------------------------------------------------*/
3774 /* genMinusBits - generates code for subtraction  of two bits      */
3775 /*-----------------------------------------------------------------*/
3776 static void
3777 genMinusBits (iCode * ic)
3778 {
3779   symbol *lbl = newiTempLabel (NULL);
3780
3781   D (emitcode (";", "genMinusBits "););
3782
3783   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3784     {
3785       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3786       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3787       emitcode ("cpl", "c");
3788       emitcode ("", "%05d$:", (lbl->key + 100));
3789       outBitC (IC_RESULT (ic));
3790     }
3791   else
3792     {
3793       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3794       emitcode ("subb", "a,acc");
3795       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3796       emitcode ("inc", "a");
3797       emitcode ("", "%05d$:", (lbl->key + 100));
3798       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3799       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3800     }
3801 }
3802
3803 /*-----------------------------------------------------------------*/
3804 /* genMinus - generates code for subtraction                       */
3805 /*-----------------------------------------------------------------*/
3806 static void
3807 genMinus (iCode * ic)
3808 {
3809   int size, offset = 0;
3810   int rSize;
3811   unsigned long lit = 0L;
3812   bool pushResult = FALSE;
3813
3814   D (emitcode (";", "genMinus "););
3815
3816   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3817   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3818   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3819       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3820     {
3821       pushResult = TRUE;
3822     }
3823   else
3824     {
3825       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3826
3827       /* special cases :- */
3828       /* if both left & right are in bit space */
3829       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3830           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3831         {
3832           genMinusBits (ic);
3833           goto release;
3834         }
3835
3836       /* if I can do an decrement instead
3837          of subtract then GOOD for ME */
3838       if (genMinusDec (ic) == TRUE)
3839         goto release;
3840
3841     }
3842
3843   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3844
3845   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3846     {
3847       CLRC;
3848     }
3849   else
3850     {
3851       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3852       lit = -(long) lit;
3853     }
3854
3855
3856   /* if literal, add a,#-lit, else normal subb */
3857   _startLazyDPSEvaluation ();
3858   while (size--)
3859     {
3860       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3861       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3862         emitcode ("subb", "a,%s",
3863                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3864       else
3865         {
3866           /* first add without previous c */
3867           if (!offset) {
3868             if (!size && lit==-1) {
3869               emitcode ("dec", "a");
3870             } else {
3871               emitcode ("add", "a,#0x%02x",
3872                         (unsigned int) (lit & 0x0FFL));
3873             }
3874           } else {
3875             emitcode ("addc", "a,#0x%02x",
3876                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3877           }
3878         }
3879
3880       if (pushResult)
3881         {
3882           emitcode ("push", "acc");
3883         }
3884       else
3885         {
3886           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3887         }
3888       offset++;
3889     }
3890   _endLazyDPSEvaluation ();
3891
3892   if (pushResult)
3893     {
3894       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3895
3896       size = getDataSize (IC_LEFT (ic));
3897       rSize = getDataSize (IC_RESULT (ic));
3898
3899       ADJUST_PUSHED_RESULT(size, rSize);
3900
3901       _startLazyDPSEvaluation ();
3902       while (size--)
3903         {
3904           emitcode ("pop", "acc");
3905           aopPut (AOP (IC_RESULT (ic)), "a", size);
3906         }
3907       _endLazyDPSEvaluation ();
3908     }
3909
3910   adjustArithmeticResult (ic);
3911
3912 release:
3913   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3914   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3915   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3916 }
3917
3918
3919 /*-----------------------------------------------------------------*/
3920 /* genMultbits :- multiplication of bits                           */
3921 /*-----------------------------------------------------------------*/
3922 static void
3923 genMultbits (operand * left,
3924              operand * right,
3925              operand * result,
3926              iCode   * ic)
3927 {
3928   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3929   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3930   aopOp(result, ic, TRUE, FALSE);
3931   outBitC (result);
3932 }
3933
3934
3935 /*-----------------------------------------------------------------*/
3936 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3937 /*-----------------------------------------------------------------*/
3938 static void
3939 genMultOneByte (operand * left,
3940                 operand * right,
3941                 operand * result,
3942                 iCode   * ic)
3943 {
3944   sym_link *opetype = operandType (result);
3945   symbol *lbl;
3946
3947
3948   /* (if two literals: the value is computed before) */
3949   /* if one literal, literal on the right */
3950   if (AOP_TYPE (left) == AOP_LIT)
3951     {
3952       operand *t = right;
3953       right = left;
3954       left = t;
3955       emitcode (";", "swapped left and right");
3956     }
3957
3958   if (SPEC_USIGN(opetype)
3959       // ignore the sign of left and right, what else can we do?
3960       || (SPEC_USIGN(operandType(left)) && 
3961           SPEC_USIGN(operandType(right)))) {
3962     // just an unsigned 8*8=8/16 multiply
3963     //emitcode (";","unsigned");
3964     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3965     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3966     emitcode ("mul", "ab");
3967    
3968     _G.accInUse++;
3969     aopOp(result, ic, TRUE, FALSE);
3970       
3971       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
3972       {
3973           // this should never happen
3974           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3975                    AOP_SIZE(result), __FILE__, lineno);
3976           exit (1);
3977       }      
3978       
3979     aopPut (AOP (result), "a", 0);
3980     _G.accInUse--;
3981     if (AOP_SIZE(result)==2) 
3982     {
3983       aopPut (AOP (result), "b", 1);
3984     }
3985     return;
3986   }
3987
3988   // we have to do a signed multiply
3989
3990   emitcode (";", "signed");
3991   emitcode ("clr", "F0"); // reset sign flag
3992   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3993
3994   lbl=newiTempLabel(NULL);
3995   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
3996   // left side is negative, 8-bit two's complement, this fails for -128
3997   emitcode ("setb", "F0"); // set sign flag
3998   emitcode ("cpl", "a");
3999   emitcode ("inc", "a");
4000
4001   emitcode ("", "%05d$:", lbl->key+100);
4002
4003   /* if literal */
4004   if (AOP_TYPE(right)==AOP_LIT) {
4005     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4006     /* AND literal negative */
4007     if ((int) val < 0) {
4008       emitcode ("cpl", "F0"); // complement sign flag
4009       emitcode ("mov", "b,#0x%02x", -val);
4010     } else {
4011       emitcode ("mov", "b,#0x%02x", val);
4012     }
4013   } else {
4014     lbl=newiTempLabel(NULL);
4015     emitcode ("mov", "b,a");
4016     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4017     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4018     // right side is negative, 8-bit two's complement
4019     emitcode ("cpl", "F0"); // complement sign flag
4020     emitcode ("cpl", "a");
4021     emitcode ("inc", "a");
4022     emitcode ("", "%05d$:", lbl->key+100);
4023   }
4024   emitcode ("mul", "ab");
4025     
4026   _G.accInUse++;
4027   aopOp(result, ic, TRUE, FALSE);
4028     
4029   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4030   {
4031     // this should never happen
4032       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4033                AOP_SIZE(result), __FILE__, lineno);
4034       exit (1);
4035   }    
4036     
4037   lbl=newiTempLabel(NULL);
4038   emitcode ("jnb", "F0,%05d$", lbl->key+100);
4039   // only ONE op was negative, we have to do a 8/16-bit two's complement
4040   emitcode ("cpl", "a"); // lsb
4041   if (AOP_SIZE(result)==1) {
4042     emitcode ("inc", "a");
4043   } else {
4044     emitcode ("add", "a,#1");
4045     emitcode ("xch", "a,b");
4046     emitcode ("cpl", "a"); // msb
4047     emitcode ("addc", "a,#0");
4048     emitcode ("xch", "a,b");
4049   }
4050
4051   emitcode ("", "%05d$:", lbl->key+100);
4052   aopPut (AOP (result), "a", 0);
4053   _G.accInUse--;
4054   if (AOP_SIZE(result)==2) {
4055     aopPut (AOP (result), "b", 1);
4056   }
4057 }
4058
4059 /*-----------------------------------------------------------------*/
4060 /* genMult - generates code for multiplication                     */
4061 /*-----------------------------------------------------------------*/
4062 static void
4063 genMult (iCode * ic)
4064 {
4065   operand *left = IC_LEFT (ic);
4066   operand *right = IC_RIGHT (ic);
4067   operand *result = IC_RESULT (ic);
4068
4069   D (emitcode (";", "genMult "););
4070
4071   /* assign the amsops */
4072   AOP_OP_2 (ic);
4073
4074   /* special cases first */
4075   /* both are bits */
4076   if (AOP_TYPE (left) == AOP_CRY &&
4077       AOP_TYPE (right) == AOP_CRY)
4078     {
4079       genMultbits (left, right, result, ic);
4080       goto release;
4081     }
4082
4083   /* if both are of size == 1 */
4084   if (AOP_SIZE (left) == 1 &&
4085       AOP_SIZE (right) == 1)
4086     {
4087       genMultOneByte (left, right, result, ic);
4088       goto release;
4089     }
4090
4091   /* should have been converted to function call */
4092   assert (1);
4093
4094 release:
4095   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4096   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4097   freeAsmop (result, NULL, ic, TRUE);
4098 }
4099
4100 /*-----------------------------------------------------------------*/
4101 /* genDivbits :- division of bits                                  */
4102 /*-----------------------------------------------------------------*/
4103 static void
4104 genDivbits (operand * left,
4105             operand * right,
4106             operand * result,
4107             iCode   * ic)
4108 {
4109
4110   char *l;
4111
4112   /* the result must be bit */
4113   LOAD_AB_FOR_DIV (left, right, l);
4114   emitcode ("div", "ab");
4115   emitcode ("rrc", "a");
4116   aopOp(result, ic, TRUE, FALSE);
4117     
4118   aopPut (AOP (result), "c", 0);
4119 }
4120
4121 /*-----------------------------------------------------------------*/
4122 /* genDivOneByte : 8 bit division                                  */
4123 /*-----------------------------------------------------------------*/
4124 static void
4125 genDivOneByte (operand * left,
4126                operand * right,
4127                operand * result,
4128                iCode   * ic)
4129 {
4130   sym_link *opetype = operandType (result);
4131   char *l;
4132   symbol *lbl;
4133   int size, offset;
4134
4135   offset = 1;
4136   /* signed or unsigned */
4137   if (SPEC_USIGN (opetype))
4138     {
4139         /* unsigned is easy */
4140         LOAD_AB_FOR_DIV (left, right, l);
4141         emitcode ("div", "ab");
4142
4143         _G.accInUse++;
4144         aopOp(result, ic, TRUE, FALSE);
4145         aopPut (AOP (result), "a", 0);
4146         _G.accInUse--;
4147
4148         size = AOP_SIZE (result) - 1;
4149         
4150         while (size--)
4151         {
4152             aopPut (AOP (result), zero, offset++);
4153         }
4154       return;
4155     }
4156
4157   /* signed is a little bit more difficult */
4158
4159   /* save the signs of the operands */
4160   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4161   MOVA (l);
4162   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4163   emitcode ("push", "acc");     /* save it on the stack */
4164
4165   /* now sign adjust for both left & right */
4166   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4167   MOVA (l);
4168   lbl = newiTempLabel (NULL);
4169   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4170   emitcode ("cpl", "a");
4171   emitcode ("inc", "a");
4172   emitcode ("", "%05d$:", (lbl->key + 100));
4173   emitcode ("mov", "b,a");
4174
4175   /* sign adjust left side */
4176   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4177   MOVA (l);
4178
4179   lbl = newiTempLabel (NULL);
4180   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4181   emitcode ("cpl", "a");
4182   emitcode ("inc", "a");
4183   emitcode ("", "%05d$:", (lbl->key + 100));
4184
4185   /* now the division */
4186   emitcode ("nop", "; workaround for DS80C390 div bug.");
4187   emitcode ("div", "ab");
4188   /* we are interested in the lower order
4189      only */
4190   emitcode ("mov", "b,a");
4191   lbl = newiTempLabel (NULL);
4192   emitcode ("pop", "acc");
4193   /* if there was an over flow we don't
4194      adjust the sign of the result */
4195   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4196   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4197   CLRC;
4198   emitcode ("clr", "a");
4199   emitcode ("subb", "a,b");
4200   emitcode ("mov", "b,a");
4201   emitcode ("", "%05d$:", (lbl->key + 100));
4202
4203   /* now we are done */
4204     _G.accInUse++;
4205     aopOp(result, ic, TRUE, FALSE);
4206     
4207     aopPut (AOP (result), "b", 0);
4208     
4209     size = AOP_SIZE (result) - 1;
4210     
4211     if (size > 0)
4212     {
4213       emitcode ("mov", "c,b.7");
4214       emitcode ("subb", "a,acc");
4215     }
4216     while (size--)
4217     {
4218         aopPut (AOP (result), "a", offset++);
4219     }
4220     _G.accInUse--;
4221
4222 }
4223
4224 /*-----------------------------------------------------------------*/
4225 /* genDiv - generates code for division                            */
4226 /*-----------------------------------------------------------------*/
4227 static void
4228 genDiv (iCode * ic)
4229 {
4230   operand *left = IC_LEFT (ic);
4231   operand *right = IC_RIGHT (ic);
4232   operand *result = IC_RESULT (ic);
4233
4234   D (emitcode (";", "genDiv "););
4235
4236   /* assign the amsops */
4237   AOP_OP_2 (ic);
4238
4239   /* special cases first */
4240   /* both are bits */
4241   if (AOP_TYPE (left) == AOP_CRY &&
4242       AOP_TYPE (right) == AOP_CRY)
4243     {
4244       genDivbits (left, right, result, ic);
4245       goto release;
4246     }
4247
4248   /* if both are of size == 1 */
4249   if (AOP_SIZE (left) == 1 &&
4250       AOP_SIZE (right) == 1)
4251     {
4252       genDivOneByte (left, right, result, ic);
4253       goto release;
4254     }
4255
4256   /* should have been converted to function call */
4257   assert (1);
4258 release:
4259   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4260   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4261   freeAsmop (result, NULL, ic, TRUE);
4262 }
4263
4264 /*-----------------------------------------------------------------*/
4265 /* genModbits :- modulus of bits                                   */
4266 /*-----------------------------------------------------------------*/
4267 static void
4268 genModbits (operand * left,
4269             operand * right,
4270             operand * result,
4271             iCode   * ic)
4272 {
4273
4274   char *l;
4275
4276   /* the result must be bit */
4277   LOAD_AB_FOR_DIV (left, right, l);
4278   emitcode ("div", "ab");
4279   emitcode ("mov", "a,b");
4280   emitcode ("rrc", "a");
4281   aopOp(result, ic, TRUE, FALSE);
4282   aopPut (AOP (result), "c", 0);
4283 }
4284
4285 /*-----------------------------------------------------------------*/
4286 /* genModOneByte : 8 bit modulus                                   */
4287 /*-----------------------------------------------------------------*/
4288 static void
4289 genModOneByte (operand * left,
4290                operand * right,
4291                operand * result,
4292                iCode   * ic)
4293 {
4294   sym_link *opetype = operandType (result);
4295   char *l;
4296   symbol *lbl;
4297
4298   /* signed or unsigned */
4299   if (SPEC_USIGN (opetype))
4300     {
4301       /* unsigned is easy */
4302       LOAD_AB_FOR_DIV (left, right, l);
4303       emitcode ("div", "ab");
4304       aopOp(result, ic, TRUE, FALSE);   
4305       aopPut (AOP (result), "b", 0);
4306       return;
4307     }
4308
4309   /* signed is a little bit more difficult */
4310
4311   /* save the signs of the operands */
4312   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4313   MOVA (l);
4314
4315   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4316   emitcode ("push", "acc");     /* save it on the stack */
4317
4318   /* now sign adjust for both left & right */
4319   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4320   MOVA (l);
4321
4322   lbl = newiTempLabel (NULL);
4323   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4324   emitcode ("cpl", "a");
4325   emitcode ("inc", "a");
4326   emitcode ("", "%05d$:", (lbl->key + 100));
4327   emitcode ("mov", "b,a");
4328
4329   /* sign adjust left side */
4330   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4331   MOVA (l);
4332
4333   lbl = newiTempLabel (NULL);
4334   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4335   emitcode ("cpl", "a");
4336   emitcode ("inc", "a");
4337   emitcode ("", "%05d$:", (lbl->key + 100));
4338
4339   /* now the multiplication */
4340   emitcode ("nop", "; workaround for DS80C390 div bug.");
4341   emitcode ("div", "ab");
4342   /* we are interested in the lower order
4343      only */
4344   lbl = newiTempLabel (NULL);
4345   emitcode ("pop", "acc");
4346   /* if there was an over flow we don't
4347      adjust the sign of the result */
4348   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4349   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4350   CLRC;
4351   emitcode ("clr", "a");
4352   emitcode ("subb", "a,b");
4353   emitcode ("mov", "b,a");
4354   emitcode ("", "%05d$:", (lbl->key + 100));
4355
4356   /* now we are done */
4357   aopOp(result, ic, TRUE, FALSE);    
4358   aopPut (AOP (result), "b", 0);
4359
4360 }
4361
4362 /*-----------------------------------------------------------------*/
4363 /* genMod - generates code for division                            */
4364 /*-----------------------------------------------------------------*/
4365 static void
4366 genMod (iCode * ic)
4367 {
4368   operand *left = IC_LEFT (ic);
4369   operand *right = IC_RIGHT (ic);
4370   operand *result = IC_RESULT (ic);
4371
4372   D (emitcode (";", "genMod "); );
4373
4374   /* assign the amsops */
4375   AOP_OP_2 (ic);
4376
4377   /* special cases first */
4378   /* both are bits */
4379   if (AOP_TYPE (left) == AOP_CRY &&
4380       AOP_TYPE (right) == AOP_CRY)
4381     {
4382       genModbits (left, right, result, ic);
4383       goto release;
4384     }
4385
4386   /* if both are of size == 1 */
4387   if (AOP_SIZE (left) == 1 &&
4388       AOP_SIZE (right) == 1)
4389     {
4390       genModOneByte (left, right, result, ic);
4391       goto release;
4392     }
4393
4394   /* should have been converted to function call */
4395   assert (1);
4396
4397 release:
4398   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4399   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4400   freeAsmop (result, NULL, ic, TRUE);
4401 }
4402
4403 /*-----------------------------------------------------------------*/
4404 /* genIfxJump :- will create a jump depending on the ifx           */
4405 /*-----------------------------------------------------------------*/
4406 static void
4407 genIfxJump (iCode * ic, char *jval)
4408 {
4409   symbol *jlbl;
4410   symbol *tlbl = newiTempLabel (NULL);
4411   char *inst;
4412
4413   D (emitcode (";", "genIfxJump ");
4414     );
4415
4416   /* if true label then we jump if condition
4417      supplied is true */
4418   if (IC_TRUE (ic))
4419     {
4420       jlbl = IC_TRUE (ic);
4421       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4422                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4423     }
4424   else
4425     {
4426       /* false label is present */
4427       jlbl = IC_FALSE (ic);
4428       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4429                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4430     }
4431   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4432     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4433   else
4434     emitcode (inst, "%05d$", tlbl->key + 100);
4435   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4436   emitcode ("", "%05d$:", tlbl->key + 100);
4437
4438   /* mark the icode as generated */
4439   ic->generated = 1;
4440 }
4441
4442 /*-----------------------------------------------------------------*/
4443 /* genCmp :- greater or less than comparison                       */
4444 /*-----------------------------------------------------------------*/
4445 static void
4446 genCmp (operand * left, operand * right,
4447         iCode * ic, iCode * ifx, int sign)
4448 {
4449   int size, offset = 0;
4450   unsigned long lit = 0L;
4451   operand *result;
4452
4453   D (emitcode (";", "genCmp");
4454     );
4455
4456   result = IC_RESULT (ic);
4457
4458   /* if left & right are bit variables */
4459   if (AOP_TYPE (left) == AOP_CRY &&
4460       AOP_TYPE (right) == AOP_CRY)
4461     {
4462       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4463       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4464     }
4465   else
4466     {
4467       /* subtract right from left if at the
4468          end the carry flag is set then we know that
4469          left is greater than right */
4470       size = max (AOP_SIZE (left), AOP_SIZE (right));
4471
4472       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4473       if ((size == 1) && !sign &&
4474           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4475         {
4476           symbol *lbl = newiTempLabel (NULL);
4477           emitcode ("cjne", "%s,%s,%05d$",
4478                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4479                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4480                     lbl->key + 100);
4481           emitcode ("", "%05d$:", lbl->key + 100);
4482         }
4483       else
4484         {
4485           if (AOP_TYPE (right) == AOP_LIT)
4486             {
4487               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4488               /* optimize if(x < 0) or if(x >= 0) */
4489               if (lit == 0L)
4490                 {
4491                   if (!sign)
4492                     {
4493                       CLRC;
4494                     }
4495                   else
4496                     {
4497                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4498
4499                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4500                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4501
4502                       aopOp (result, ic, FALSE, FALSE);
4503
4504                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4505                         {
4506                           freeAsmop (result, NULL, ic, TRUE);
4507                           genIfxJump (ifx, "acc.7");
4508                           return;
4509                         }
4510                       else
4511                         {
4512                           emitcode ("rlc", "a");
4513                         }
4514                       goto release_freedLR;
4515                     }
4516                   goto release;
4517                 }
4518             }
4519           CLRC;
4520           while (size--)
4521             {
4522               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4523               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4524               emitcode (";", "genCmp #2");
4525               if (sign && (size == 0))
4526                 {
4527                   emitcode (";", "genCmp #3");
4528                   emitcode ("xrl", "a,#0x80");
4529                   if (AOP_TYPE (right) == AOP_LIT)
4530                     {
4531                       unsigned long lit = (unsigned long)
4532                       floatFromVal (AOP (right)->aopu.aop_lit);
4533                       emitcode (";", "genCmp #3.1");
4534                       emitcode ("subb", "a,#0x%02x",
4535                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4536                     }
4537                   else
4538                     {
4539                       emitcode (";", "genCmp #3.2");
4540                       if (AOP_NEEDSACC (right))
4541                         {
4542                           emitcode ("push", "acc");
4543                         }
4544                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4545                                                        FALSE, FALSE, FALSE));
4546                       emitcode ("xrl", "b,#0x80");
4547                       if (AOP_NEEDSACC (right))
4548                         {
4549                           emitcode ("pop", "acc");
4550                         }
4551                       emitcode ("subb", "a,b");
4552                     }
4553                 }
4554               else
4555                 {
4556                   const char *s;
4557
4558                   emitcode (";", "genCmp #4");
4559                   if (AOP_NEEDSACC (right))
4560                     {
4561                       /* Yuck!! */
4562                       emitcode (";", "genCmp #4.1");
4563                       emitcode ("xch", "a, b");
4564                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4565                       emitcode ("xch", "a, b");
4566                       s = "b";
4567                     }
4568                   else
4569                     {
4570                       emitcode (";", "genCmp #4.2");
4571                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4572                     }
4573
4574                   emitcode ("subb", "a,%s", s);
4575                 }
4576             }
4577         }
4578     }
4579
4580 release:
4581 /* Don't need the left & right operands any more; do need the result. */
4582   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4583   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4584
4585   aopOp (result, ic, FALSE, FALSE);
4586
4587 release_freedLR:
4588
4589   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4590     {
4591       outBitC (result);
4592     }
4593   else
4594     {
4595       /* if the result is used in the next
4596          ifx conditional branch then generate
4597          code a little differently */
4598       if (ifx)
4599         {
4600           genIfxJump (ifx, "c");
4601         }
4602       else
4603         {
4604           outBitC (result);
4605         }
4606       /* leave the result in acc */
4607     }
4608   freeAsmop (result, NULL, ic, TRUE);
4609 }
4610
4611 /*-----------------------------------------------------------------*/
4612 /* genCmpGt :- greater than comparison                             */
4613 /*-----------------------------------------------------------------*/
4614 static void
4615 genCmpGt (iCode * ic, iCode * ifx)
4616 {
4617   operand *left, *right;
4618   sym_link *letype, *retype;
4619   int sign;
4620
4621   D (emitcode (";", "genCmpGt ");
4622     );
4623
4624   left = IC_LEFT (ic);
4625   right = IC_RIGHT (ic);
4626
4627   letype = getSpec (operandType (left));
4628   retype = getSpec (operandType (right));
4629   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4630
4631   /* assign the left & right amsops */
4632   AOP_OP_2 (ic);
4633
4634   genCmp (right, left, ic, ifx, sign);
4635 }
4636
4637 /*-----------------------------------------------------------------*/
4638 /* genCmpLt - less than comparisons                                */
4639 /*-----------------------------------------------------------------*/
4640 static void
4641 genCmpLt (iCode * ic, iCode * ifx)
4642 {
4643   operand *left, *right;
4644   sym_link *letype, *retype;
4645   int sign;
4646
4647   D (emitcode (";", "genCmpLt "););
4648
4649   left = IC_LEFT (ic);
4650   right = IC_RIGHT (ic);
4651
4652   letype = getSpec (operandType (left));
4653   retype = getSpec (operandType (right));
4654   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4655
4656   /* assign the left & right amsops */
4657   AOP_OP_2 (ic);
4658
4659   genCmp (left, right, ic, ifx, sign);
4660 }
4661
4662 /*-----------------------------------------------------------------*/
4663 /* gencjneshort - compare and jump if not equal                    */
4664 /*-----------------------------------------------------------------*/
4665 static void
4666 gencjneshort (operand * left, operand * right, symbol * lbl)
4667 {
4668   int size = max (AOP_SIZE (left), AOP_SIZE (right));
4669   int offset = 0;
4670   unsigned long lit = 0L;
4671
4672   D (emitcode (";", "gencjneshort");
4673     );
4674
4675   /* if the left side is a literal or
4676      if the right is in a pointer register and left
4677      is not */
4678   if ((AOP_TYPE (left) == AOP_LIT) ||
4679       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4680     {
4681       operand *t = right;
4682       right = left;
4683       left = t;
4684     }
4685
4686   if (AOP_TYPE (right) == AOP_LIT)
4687     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4688
4689   if (opIsGptr (left) || opIsGptr (right))
4690     {
4691       /* We are comparing a generic pointer to something.
4692        * Exclude the generic type byte from the comparison.
4693        */
4694       size--;
4695       D (emitcode (";", "cjneshort: generic ptr special case.");
4696         )
4697     }
4698
4699
4700   /* if the right side is a literal then anything goes */
4701   if (AOP_TYPE (right) == AOP_LIT &&
4702       AOP_TYPE (left) != AOP_DIR)
4703     {
4704       while (size--)
4705         {
4706           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4707           MOVA (l);
4708           emitcode ("cjne", "a,%s,%05d$",
4709                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4710                     lbl->key + 100);
4711           offset++;
4712         }
4713     }
4714
4715   /* if the right side is in a register or in direct space or
4716      if the left is a pointer register & right is not */
4717   else if (AOP_TYPE (right) == AOP_REG ||
4718            AOP_TYPE (right) == AOP_DIR ||
4719            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4720            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4721     {
4722       while (size--)
4723         {
4724           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4725           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4726               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4727             emitcode ("jnz", "%05d$", lbl->key + 100);
4728           else
4729             emitcode ("cjne", "a,%s,%05d$",
4730                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
4731                       lbl->key + 100);
4732           offset++;
4733         }
4734     }
4735   else
4736     {
4737       /* right is a pointer reg need both a & b */
4738       while (size--)
4739         {
4740           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
4741           if (strcmp (l, "b"))
4742             emitcode ("mov", "b,%s", l);
4743           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
4744           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4745           offset++;
4746         }
4747     }
4748 }
4749
4750 /*-----------------------------------------------------------------*/
4751 /* gencjne - compare and jump if not equal                         */
4752 /*-----------------------------------------------------------------*/
4753 static void
4754 gencjne (operand * left, operand * right, symbol * lbl)
4755 {
4756   symbol *tlbl = newiTempLabel (NULL);
4757
4758   D (emitcode (";", "gencjne");
4759     );
4760
4761   gencjneshort (left, right, lbl);
4762
4763   emitcode ("mov", "a,%s", one);
4764   emitcode ("sjmp", "%05d$", tlbl->key + 100);
4765   emitcode ("", "%05d$:", lbl->key + 100);
4766   emitcode ("clr", "a");
4767   emitcode ("", "%05d$:", tlbl->key + 100);
4768 }
4769
4770 /*-----------------------------------------------------------------*/
4771 /* genCmpEq - generates code for equal to                          */
4772 /*-----------------------------------------------------------------*/
4773 static void
4774 genCmpEq (iCode * ic, iCode * ifx)
4775 {
4776   operand *left, *right, *result;
4777
4778   D (emitcode (";", "genCmpEq ");
4779     );
4780
4781   AOP_OP_2 (ic);
4782   AOP_SET_LOCALS (ic);
4783
4784   /* if literal, literal on the right or
4785      if the right is in a pointer register and left
4786      is not */
4787   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4788       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4789     {
4790       operand *t = IC_RIGHT (ic);
4791       IC_RIGHT (ic) = IC_LEFT (ic);
4792       IC_LEFT (ic) = t;
4793     }
4794
4795   if (ifx &&                    /* !AOP_SIZE(result) */
4796       OP_SYMBOL (result) &&
4797       OP_SYMBOL (result)->regType == REG_CND)
4798     {
4799       symbol *tlbl;
4800       /* if they are both bit variables */
4801       if (AOP_TYPE (left) == AOP_CRY &&
4802           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4803         {
4804           if (AOP_TYPE (right) == AOP_LIT)
4805             {
4806               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4807               if (lit == 0L)
4808                 {
4809                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4810                   emitcode ("cpl", "c");
4811                 }
4812               else if (lit == 1L)
4813                 {
4814                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4815                 }
4816               else
4817                 {
4818                   emitcode ("clr", "c");
4819                 }
4820               /* AOP_TYPE(right) == AOP_CRY */
4821             }
4822           else
4823             {
4824               symbol *lbl = newiTempLabel (NULL);
4825               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4826               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4827               emitcode ("cpl", "c");
4828               emitcode ("", "%05d$:", (lbl->key + 100));
4829             }
4830           /* if true label then we jump if condition
4831              supplied is true */
4832           tlbl = newiTempLabel (NULL);
4833           if (IC_TRUE (ifx))
4834             {
4835               emitcode ("jnc", "%05d$", tlbl->key + 100);
4836               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4837             }
4838           else
4839             {
4840               emitcode ("jc", "%05d$", tlbl->key + 100);
4841               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4842             }
4843           emitcode ("", "%05d$:", tlbl->key + 100);
4844         }
4845       else
4846         {
4847           tlbl = newiTempLabel (NULL);
4848           gencjneshort (left, right, tlbl);
4849           if (IC_TRUE (ifx))
4850             {
4851               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4852               emitcode ("", "%05d$:", tlbl->key + 100);
4853             }
4854           else
4855             {
4856               symbol *lbl = newiTempLabel (NULL);
4857               emitcode ("sjmp", "%05d$", lbl->key + 100);
4858               emitcode ("", "%05d$:", tlbl->key + 100);
4859               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4860               emitcode ("", "%05d$:", lbl->key + 100);
4861             }
4862         }
4863       /* mark the icode as generated */
4864       ifx->generated = 1;
4865
4866       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4867       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4868       return;
4869     }
4870
4871   /* if they are both bit variables */
4872   if (AOP_TYPE (left) == AOP_CRY &&
4873       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4874     {
4875       if (AOP_TYPE (right) == AOP_LIT)
4876         {
4877           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4878           if (lit == 0L)
4879             {
4880               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4881               emitcode ("cpl", "c");
4882             }
4883           else if (lit == 1L)
4884             {
4885               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4886             }
4887           else
4888             {
4889               emitcode ("clr", "c");
4890             }
4891           /* AOP_TYPE(right) == AOP_CRY */
4892         }
4893       else
4894         {
4895           symbol *lbl = newiTempLabel (NULL);
4896           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4897           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4898           emitcode ("cpl", "c");
4899           emitcode ("", "%05d$:", (lbl->key + 100));
4900         }
4901
4902       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4903       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4904
4905       aopOp (result, ic, TRUE, FALSE);
4906
4907       /* c = 1 if egal */
4908       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4909         {
4910           outBitC (result);
4911           goto release;
4912         }
4913       if (ifx)
4914         {
4915           genIfxJump (ifx, "c");
4916           goto release;
4917         }
4918       /* if the result is used in an arithmetic operation
4919          then put the result in place */
4920       outBitC (result);
4921     }
4922   else
4923     {
4924       gencjne (left, right, newiTempLabel (NULL));
4925
4926       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4927       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4928
4929       aopOp (result, ic, TRUE, FALSE);
4930
4931       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4932         {
4933           aopPut (AOP (result), "a", 0);
4934           goto release;
4935         }
4936       if (ifx)
4937         {
4938           genIfxJump (ifx, "a");
4939           goto release;
4940         }
4941       /* if the result is used in an arithmetic operation
4942          then put the result in place */
4943       if (AOP_TYPE (result) != AOP_CRY)
4944         outAcc (result);
4945       /* leave the result in acc */
4946     }
4947
4948 release:
4949   freeAsmop (result, NULL, ic, TRUE);
4950 }
4951
4952 /*-----------------------------------------------------------------*/
4953 /* ifxForOp - returns the icode containing the ifx for operand     */
4954 /*-----------------------------------------------------------------*/
4955 static iCode *
4956 ifxForOp (operand * op, iCode * ic)
4957 {
4958   /* if true symbol then needs to be assigned */
4959   if (IS_TRUE_SYMOP (op))
4960     return NULL;
4961
4962   /* if this has register type condition and
4963      the next instruction is ifx with the same operand
4964      and live to of the operand is upto the ifx only then */
4965   if (ic->next &&
4966       ic->next->op == IFX &&
4967       IC_COND (ic->next)->key == op->key &&
4968       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4969     return ic->next;
4970
4971   return NULL;
4972 }
4973 /*-----------------------------------------------------------------*/
4974 /* genAndOp - for && operation                                     */
4975 /*-----------------------------------------------------------------*/
4976 static void
4977 genAndOp (iCode * ic)
4978 {
4979   operand *left, *right, *result;
4980   symbol *tlbl;
4981
4982   D (emitcode (";", "genAndOp "););
4983
4984   /* note here that && operations that are in an
4985      if statement are taken away by backPatchLabels
4986      only those used in arthmetic operations remain */
4987   AOP_OP_2 (ic);
4988   AOP_SET_LOCALS (ic);
4989
4990   /* if both are bit variables */
4991   if (AOP_TYPE (left) == AOP_CRY &&
4992       AOP_TYPE (right) == AOP_CRY)
4993     {
4994       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4995       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4996       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4997       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4998   
4999       aopOp (result,ic,FALSE, FALSE);
5000       outBitC (result);
5001     }
5002   else
5003     {
5004       tlbl = newiTempLabel (NULL);
5005       toBoolean (left);
5006       emitcode ("jz", "%05d$", tlbl->key + 100);
5007       toBoolean (right);
5008       emitcode ("", "%05d$:", tlbl->key + 100);
5009       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5010       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5011   
5012       aopOp (result,ic,FALSE, FALSE);
5013       outBitAcc (result);
5014     }
5015     freeAsmop (result, NULL, ic, TRUE);
5016 }
5017
5018
5019 /*-----------------------------------------------------------------*/
5020 /* genOrOp - for || operation                                      */
5021 /*-----------------------------------------------------------------*/
5022 static void
5023 genOrOp (iCode * ic)
5024 {
5025   operand *left, *right, *result;
5026   symbol *tlbl;
5027
5028   D (emitcode (";", "genOrOp "););
5029
5030   /* note here that || operations that are in an
5031      if statement are taken away by backPatchLabels
5032      only those used in arthmetic operations remain */
5033   AOP_OP_2 (ic);
5034   AOP_SET_LOCALS (ic);
5035
5036   /* if both are bit variables */
5037   if (AOP_TYPE (left) == AOP_CRY &&
5038       AOP_TYPE (right) == AOP_CRY)
5039     {
5040       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5041       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5042       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5043       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5044   
5045       aopOp (result,ic,FALSE, FALSE);
5046       
5047       outBitC (result);
5048     }
5049   else
5050     {
5051       tlbl = newiTempLabel (NULL);
5052       toBoolean (left);
5053       emitcode ("jnz", "%05d$", tlbl->key + 100);
5054       toBoolean (right);
5055       emitcode ("", "%05d$:", tlbl->key + 100);
5056       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5057       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5058   
5059       aopOp (result,ic,FALSE, FALSE);
5060       
5061       outBitAcc (result);
5062     }
5063
5064   freeAsmop (result, NULL, ic, TRUE);
5065 }
5066
5067 /*-----------------------------------------------------------------*/
5068 /* isLiteralBit - test if lit == 2^n                               */
5069 /*-----------------------------------------------------------------*/
5070 static int
5071 isLiteralBit (unsigned long lit)
5072 {
5073   unsigned long pw[32] =
5074   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5075    0x100L, 0x200L, 0x400L, 0x800L,
5076    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5077    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5078    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5079    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5080    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5081   int idx;
5082
5083   for (idx = 0; idx < 32; idx++)
5084     if (lit == pw[idx])
5085       return idx + 1;
5086   return 0;
5087 }
5088
5089 /*-----------------------------------------------------------------*/
5090 /* continueIfTrue -                                                */
5091 /*-----------------------------------------------------------------*/
5092 static void
5093 continueIfTrue (iCode * ic)
5094 {
5095   if (IC_TRUE (ic))
5096     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5097   ic->generated = 1;
5098 }
5099
5100 /*-----------------------------------------------------------------*/
5101 /* jmpIfTrue -                                                     */
5102 /*-----------------------------------------------------------------*/
5103 static void
5104 jumpIfTrue (iCode * ic)
5105 {
5106   if (!IC_TRUE (ic))
5107     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5108   ic->generated = 1;
5109 }
5110
5111 /*-----------------------------------------------------------------*/
5112 /* jmpTrueOrFalse -                                                */
5113 /*-----------------------------------------------------------------*/
5114 static void
5115 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5116 {
5117   // ugly but optimized by peephole
5118   if (IC_TRUE (ic))
5119     {
5120       symbol *nlbl = newiTempLabel (NULL);
5121       emitcode ("sjmp", "%05d$", nlbl->key + 100);
5122       emitcode ("", "%05d$:", tlbl->key + 100);
5123       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5124       emitcode ("", "%05d$:", nlbl->key + 100);
5125     }
5126   else
5127     {
5128       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5129       emitcode ("", "%05d$:", tlbl->key + 100);
5130     }
5131   ic->generated = 1;
5132 }
5133
5134 // Generate code to perform a bit-wise logic operation
5135 // on two operands in far space (assumed to already have been 
5136 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5137 // in far space. This requires pushing the result on the stack
5138 // then popping it into the result.
5139 static void
5140 genFarFarLogicOp(iCode *ic, char *logicOp)
5141 {
5142       int size, resultSize, compSize;
5143       int offset = 0;
5144       
5145       TR_AP("#5");
5146       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5147       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5148                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5149       
5150       _startLazyDPSEvaluation();
5151       for (size = compSize; (size--); offset++)
5152       {
5153           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5154           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5155           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5156           
5157           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5158           emitcode ("push", "acc");
5159       }
5160       _endLazyDPSEvaluation();
5161      
5162       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5163       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5164       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5165      
5166       resultSize = AOP_SIZE(IC_RESULT(ic));
5167
5168       ADJUST_PUSHED_RESULT(compSize, resultSize);
5169
5170       _startLazyDPSEvaluation();
5171       while (compSize--)
5172       {
5173           emitcode ("pop", "acc");
5174           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5175       }
5176       _endLazyDPSEvaluation();
5177       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5178 }
5179
5180
5181 /*-----------------------------------------------------------------*/
5182 /* genAnd  - code for and                                          */
5183 /*-----------------------------------------------------------------*/
5184 static void
5185 genAnd (iCode * ic, iCode * ifx)
5186 {
5187   operand *left, *right, *result;
5188   int size, offset = 0;
5189   unsigned long lit = 0L;
5190   int bytelit = 0;
5191   char buffer[10];
5192   bool pushResult;
5193
5194   D (emitcode (";", "genAnd "););
5195
5196   AOP_OP_3_NOFATAL (ic, pushResult);
5197   AOP_SET_LOCALS (ic);
5198
5199   if (pushResult)
5200   {
5201       genFarFarLogicOp(ic, "anl");
5202       return;
5203   }  
5204
5205 #ifdef DEBUG_TYPE
5206   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5207             AOP_TYPE (result),
5208             AOP_TYPE (left), AOP_TYPE (right));
5209   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5210             AOP_SIZE (result),
5211             AOP_SIZE (left), AOP_SIZE (right));
5212 #endif
5213
5214   /* if left is a literal & right is not then exchange them */
5215   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5216       AOP_NEEDSACC (left))
5217     {
5218       operand *tmp = right;
5219       right = left;
5220       left = tmp;
5221     }
5222
5223   /* if result = right then exchange them */
5224   if (sameRegs (AOP (result), AOP (right)))
5225     {
5226       operand *tmp = right;
5227       right = left;
5228       left = tmp;
5229     }
5230
5231   /* if right is bit then exchange them */
5232   if (AOP_TYPE (right) == AOP_CRY &&
5233       AOP_TYPE (left) != AOP_CRY)
5234     {
5235       operand *tmp = right;
5236       right = left;
5237       left = tmp;
5238     }
5239   if (AOP_TYPE (right) == AOP_LIT)
5240     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5241
5242   size = AOP_SIZE (result);
5243
5244   // if(bit & yy)
5245   // result = bit & yy;
5246   if (AOP_TYPE (left) == AOP_CRY)
5247     {
5248       // c = bit & literal;
5249       if (AOP_TYPE (right) == AOP_LIT)
5250         {
5251           if (lit & 1)
5252             {
5253               if (size && sameRegs (AOP (result), AOP (left)))
5254                 // no change
5255                 goto release;
5256               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5257             }
5258           else
5259             {
5260               // bit(result) = 0;
5261               if (size && (AOP_TYPE (result) == AOP_CRY))
5262                 {
5263                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5264                   goto release;
5265                 }
5266               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5267                 {
5268                   jumpIfTrue (ifx);
5269                   goto release;
5270                 }
5271               emitcode ("clr", "c");
5272             }
5273         }
5274       else
5275         {
5276           if (AOP_TYPE (right) == AOP_CRY)
5277             {
5278               // c = bit & bit;
5279               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5280               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5281             }
5282           else
5283             {
5284               // c = bit & val;
5285               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5286               // c = lsb
5287               emitcode ("rrc", "a");
5288               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5289             }
5290         }
5291       // bit = c
5292       // val = c
5293       if (size)
5294         outBitC (result);
5295       // if(bit & ...)
5296       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5297         genIfxJump (ifx, "c");
5298       goto release;
5299     }
5300
5301   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5302   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5303   if ((AOP_TYPE (right) == AOP_LIT) &&
5304       (AOP_TYPE (result) == AOP_CRY) &&
5305       (AOP_TYPE (left) != AOP_CRY))
5306     {
5307       int posbit = isLiteralBit (lit);
5308       /* left &  2^n */
5309       if (posbit)
5310         {
5311           posbit--;
5312           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5313           // bit = left & 2^n
5314           if (size)
5315             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5316           // if(left &  2^n)
5317           else
5318             {
5319               if (ifx)
5320                 {
5321                   sprintf (buffer, "acc.%d", posbit & 0x07);
5322                   genIfxJump (ifx, buffer);
5323                 }
5324               goto release;
5325             }
5326         }
5327       else
5328         {
5329           symbol *tlbl = newiTempLabel (NULL);
5330           int sizel = AOP_SIZE (left);
5331           if (size)
5332             emitcode ("setb", "c");
5333           while (sizel--)
5334             {
5335               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5336                 {
5337                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5338                   // byte ==  2^n ?
5339                   if ((posbit = isLiteralBit (bytelit)) != 0)
5340                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5341                   else
5342                     {
5343                       if (bytelit != 0x0FFL)
5344                         emitcode ("anl", "a,%s",
5345                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5346                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5347                     }
5348                 }
5349               offset++;
5350             }
5351           // bit = left & literal
5352           if (size)
5353             {
5354               emitcode ("clr", "c");
5355               emitcode ("", "%05d$:", tlbl->key + 100);
5356             }
5357           // if(left & literal)
5358           else
5359             {
5360               if (ifx)
5361                 jmpTrueOrFalse (ifx, tlbl);
5362               goto release;
5363             }
5364         }
5365       outBitC (result);
5366       goto release;
5367     }
5368
5369   /* if left is same as result */
5370   if (sameRegs (AOP (result), AOP (left)))
5371     {
5372       for (; size--; offset++)
5373         {
5374           if (AOP_TYPE (right) == AOP_LIT)
5375             {
5376               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5377                 continue;
5378               else if (bytelit == 0)
5379                 aopPut (AOP (result), zero, offset);
5380               else if (IS_AOP_PREG (result))
5381                 {
5382                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5383                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5384                   aopPut (AOP (result), "a", offset);
5385                 }
5386               else
5387                 emitcode ("anl", "%s,%s",
5388                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5389                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5390             }
5391           else
5392             {
5393               if (AOP_TYPE (left) == AOP_ACC)
5394                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5395               else
5396                 {
5397                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5398                   if (IS_AOP_PREG (result))
5399                     {
5400                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5401                       aopPut (AOP (result), "a", offset);
5402
5403                     }
5404                   else
5405                     emitcode ("anl", "%s,a",
5406                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5407                 }
5408             }
5409         }
5410     }
5411   else
5412     {
5413       // left & result in different registers
5414       if (AOP_TYPE (result) == AOP_CRY)
5415         {
5416           // result = bit
5417           // if(size), result in bit
5418           // if(!size && ifx), conditional oper: if(left & right)
5419           symbol *tlbl = newiTempLabel (NULL);
5420           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5421           if (size)
5422             emitcode ("setb", "c");
5423           while (sizer--)
5424             {
5425               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5426                 emitcode ("anl", "a,%s",
5427                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5428               } else {
5429                 if (AOP_TYPE(left)==AOP_ACC) {
5430                   emitcode("mov", "b,a");
5431                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5432                   emitcode("anl", "a,b");
5433                 }else {
5434                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5435                   emitcode ("anl", "a,%s",
5436                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5437                 }
5438               }
5439               emitcode ("jnz", "%05d$", tlbl->key + 100);
5440               offset++;
5441             }
5442           if (size)
5443             {
5444               CLRC;
5445               emitcode ("", "%05d$:", tlbl->key + 100);
5446               outBitC (result);
5447             }
5448           else if (ifx)
5449             jmpTrueOrFalse (ifx, tlbl);
5450         }
5451       else
5452         {
5453           for (; (size--); offset++)
5454             {
5455               // normal case
5456               // result = left & right
5457               if (AOP_TYPE (right) == AOP_LIT)
5458                 {
5459                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5460                     {
5461                       aopPut (AOP (result),
5462                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5463                               offset);
5464                       continue;
5465                     }
5466                   else if (bytelit == 0)
5467                     {
5468                       aopPut (AOP (result), zero, offset);
5469                       continue;
5470                     }
5471                   D (emitcode (";", "better literal AND.");
5472                     );
5473                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5474                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5475                                                     FALSE, FALSE, FALSE));
5476
5477                 }
5478               else
5479                 {
5480                   // faster than result <- left, anl result,right
5481                   // and better if result is SFR
5482                   if (AOP_TYPE (left) == AOP_ACC)
5483                     {
5484                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5485                                                        FALSE, FALSE, FALSE));
5486                     }
5487                   else
5488                     {
5489                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5490                       emitcode ("anl", "a,%s",
5491                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5492                     }
5493                 }
5494               aopPut (AOP (result), "a", offset);
5495             }
5496         }
5497     }
5498
5499 release:
5500   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5501   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5502   freeAsmop (result, NULL, ic, TRUE);
5503 }
5504
5505
5506 /*-----------------------------------------------------------------*/
5507 /* genOr  - code for or                                            */
5508 /*-----------------------------------------------------------------*/
5509 static void
5510 genOr (iCode * ic, iCode * ifx)
5511 {
5512   operand *left, *right, *result;
5513   int size, offset = 0;
5514   unsigned long lit = 0L;
5515   bool     pushResult;
5516
5517   D (emitcode (";", "genOr "););
5518
5519   AOP_OP_3_NOFATAL (ic, pushResult);
5520   AOP_SET_LOCALS (ic);
5521
5522   if (pushResult)
5523   {
5524       genFarFarLogicOp(ic, "orl");
5525       return;
5526   }
5527
5528
5529 #ifdef DEBUG_TYPE
5530   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5531             AOP_TYPE (result),
5532             AOP_TYPE (left), AOP_TYPE (right));
5533   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5534             AOP_SIZE (result),
5535             AOP_SIZE (left), AOP_SIZE (right));
5536 #endif
5537
5538   /* if left is a literal & right is not then exchange them */
5539   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5540       AOP_NEEDSACC (left))
5541     {
5542       operand *tmp = right;
5543       right = left;
5544       left = tmp;
5545     }
5546
5547   /* if result = right then exchange them */
5548   if (sameRegs (AOP (result), AOP (right)))
5549     {
5550       operand *tmp = right;
5551       right = left;
5552       left = tmp;
5553     }
5554
5555   /* if right is bit then exchange them */
5556   if (AOP_TYPE (right) == AOP_CRY &&
5557       AOP_TYPE (left) != AOP_CRY)
5558     {
5559       operand *tmp = right;
5560       right = left;
5561       left = tmp;
5562     }
5563   if (AOP_TYPE (right) == AOP_LIT)
5564     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5565
5566   size = AOP_SIZE (result);
5567
5568   // if(bit | yy)
5569   // xx = bit | yy;
5570   if (AOP_TYPE (left) == AOP_CRY)
5571     {
5572       if (AOP_TYPE (right) == AOP_LIT)
5573         {
5574           // c = bit & literal;
5575           if (lit)
5576             {
5577               // lit != 0 => result = 1
5578               if (AOP_TYPE (result) == AOP_CRY)
5579                 {
5580                   if (size)
5581                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5582                   else if (ifx)
5583                     continueIfTrue (ifx);
5584                   goto release;
5585                 }
5586               emitcode ("setb", "c");
5587             }
5588           else
5589             {
5590               // lit == 0 => result = left
5591               if (size && sameRegs (AOP (result), AOP (left)))
5592                 goto release;
5593               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5594             }
5595         }
5596       else
5597         {
5598           if (AOP_TYPE (right) == AOP_CRY)
5599             {
5600               // c = bit | bit;
5601               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5602               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5603             }
5604           else
5605             {
5606               // c = bit | val;
5607               symbol *tlbl = newiTempLabel (NULL);
5608               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5609                 emitcode ("setb", "c");
5610               emitcode ("jb", "%s,%05d$",
5611                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
5612               toBoolean (right);
5613               emitcode ("jnz", "%05d$", tlbl->key + 100);
5614               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5615                 {
5616                   jmpTrueOrFalse (ifx, tlbl);
5617                   goto release;
5618                 }
5619               else
5620                 {
5621                   CLRC;
5622                   emitcode ("", "%05d$:", tlbl->key + 100);
5623                 }
5624             }
5625         }
5626       // bit = c
5627       // val = c
5628       if (size)
5629         outBitC (result);
5630       // if(bit | ...)
5631       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5632         genIfxJump (ifx, "c");
5633       goto release;
5634     }
5635
5636   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5637   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5638   if ((AOP_TYPE (right) == AOP_LIT) &&
5639       (AOP_TYPE (result) == AOP_CRY) &&
5640       (AOP_TYPE (left) != AOP_CRY))
5641     {
5642       if (lit)
5643         {
5644           // result = 1
5645           if (size)
5646             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5647           else
5648             continueIfTrue (ifx);
5649           goto release;
5650         }
5651       else
5652         {
5653           // lit = 0, result = boolean(left)
5654           if (size)
5655             emitcode ("setb", "c");
5656           toBoolean (right);
5657           if (size)
5658             {
5659               symbol *tlbl = newiTempLabel (NULL);
5660               emitcode ("jnz", "%05d$", tlbl->key + 100);
5661               CLRC;
5662               emitcode ("", "%05d$:", tlbl->key + 100);
5663             }
5664           else
5665             {
5666               genIfxJump (ifx, "a");
5667               goto release;
5668             }
5669         }
5670       outBitC (result);
5671       goto release;
5672     }
5673
5674   /* if left is same as result */
5675   if (sameRegs (AOP (result), AOP (left)))
5676     {
5677       for (; size--; offset++)
5678         {
5679           if (AOP_TYPE (right) == AOP_LIT)
5680             {
5681               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5682                 {
5683                   continue;
5684                 }
5685               else
5686                 {
5687                   if (IS_AOP_PREG (left))
5688                     {
5689                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5690                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5691                       aopPut (AOP (result), "a", offset);
5692                     }
5693                   else
5694                     {
5695                       emitcode ("orl", "%s,%s",
5696                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5697                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5698                     }
5699                 }
5700             }
5701           else
5702             {
5703               if (AOP_TYPE (left) == AOP_ACC)
5704                 {
5705                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5706                 }
5707               else
5708                 {
5709                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5710                   if (IS_AOP_PREG (left))
5711                     {
5712                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5713                       aopPut (AOP (result), "a", offset);
5714                     }
5715                   else
5716                     {
5717                       emitcode ("orl", "%s,a",
5718                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5719                     }
5720                 }
5721             }
5722         }
5723     }
5724   else
5725     {
5726       // left & result in different registers
5727       if (AOP_TYPE (result) == AOP_CRY)
5728         {
5729           // result = bit
5730           // if(size), result in bit
5731           // if(!size && ifx), conditional oper: if(left | right)
5732           symbol *tlbl = newiTempLabel (NULL);
5733           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5734           if (size)
5735             emitcode ("setb", "c");
5736           while (sizer--)
5737             {
5738               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5739                 emitcode ("orl", "a,%s",
5740                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5741               } else {
5742                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5743                 emitcode ("orl", "a,%s",
5744                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5745               }
5746               emitcode ("jnz", "%05d$", tlbl->key + 100);
5747               offset++;
5748             }
5749           if (size)
5750             {
5751               CLRC;
5752               emitcode ("", "%05d$:", tlbl->key + 100);
5753               outBitC (result);
5754             }
5755           else if (ifx)
5756             jmpTrueOrFalse (ifx, tlbl);
5757         }
5758       else
5759         {
5760             _startLazyDPSEvaluation();
5761           for (; (size--); offset++)
5762             {
5763               // normal case
5764               // result = left & right
5765               if (AOP_TYPE (right) == AOP_LIT)
5766                 {
5767                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5768                     {
5769                       aopPut (AOP (result),
5770                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5771                               offset);
5772                       continue;
5773                     }
5774                   D (emitcode (";", "better literal OR."););
5775                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5776                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5777                                                     FALSE, FALSE, FALSE));
5778
5779                 }
5780               else
5781                 {
5782                   // faster than result <- left, anl result,right
5783                   // and better if result is SFR
5784                   if (AOP_TYPE (left) == AOP_ACC)
5785                     {
5786                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5787                                                        FALSE, FALSE, FALSE));
5788                     }
5789                   else
5790                     {
5791                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5792                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5793                       {
5794                           emitcode("mov", "b,a");
5795                           rOp = "b";
5796                       }
5797                         
5798                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5799                       emitcode ("orl", "a,%s", rOp);
5800                     }
5801                 }
5802               aopPut (AOP (result), "a", offset);
5803             }
5804             _endLazyDPSEvaluation();
5805         }
5806     }
5807
5808 release:
5809   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5810   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5811   freeAsmop (result, NULL, ic, TRUE);
5812 }
5813
5814 /*-----------------------------------------------------------------*/
5815 /* genXor - code for xclusive or                                   */
5816 /*-----------------------------------------------------------------*/
5817 static void
5818 genXor (iCode * ic, iCode * ifx)
5819 {
5820   operand *left, *right, *result;
5821   int size, offset = 0;
5822   unsigned long lit = 0L;
5823   bool pushResult;
5824
5825   D (emitcode (";", "genXor "););
5826
5827   AOP_OP_3_NOFATAL (ic, pushResult);
5828   AOP_SET_LOCALS (ic);
5829
5830   if (pushResult)
5831   {
5832       genFarFarLogicOp(ic, "xrl");
5833       return;
5834   }  
5835
5836 #ifdef DEBUG_TYPE
5837   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5838             AOP_TYPE (result),
5839             AOP_TYPE (left), AOP_TYPE (right));
5840   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5841             AOP_SIZE (result),
5842             AOP_SIZE (left), AOP_SIZE (right));
5843 #endif
5844
5845   /* if left is a literal & right is not ||
5846      if left needs acc & right does not */
5847   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5848       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5849     {
5850       operand *tmp = right;
5851       right = left;
5852       left = tmp;
5853     }
5854
5855   /* if result = right then exchange them */
5856   if (sameRegs (AOP (result), AOP (right)))
5857     {
5858       operand *tmp = right;
5859       right = left;
5860       left = tmp;
5861     }
5862
5863   /* if right is bit then exchange them */
5864   if (AOP_TYPE (right) == AOP_CRY &&
5865       AOP_TYPE (left) != AOP_CRY)
5866     {
5867       operand *tmp = right;
5868       right = left;
5869       left = tmp;
5870     }
5871   if (AOP_TYPE (right) == AOP_LIT)
5872     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5873
5874   size = AOP_SIZE (result);
5875
5876   // if(bit ^ yy)
5877   // xx = bit ^ yy;
5878   if (AOP_TYPE (left) == AOP_CRY)
5879     {
5880       if (AOP_TYPE (right) == AOP_LIT)
5881         {
5882           // c = bit & literal;
5883           if (lit >> 1)
5884             {
5885               // lit>>1  != 0 => result = 1
5886               if (AOP_TYPE (result) == AOP_CRY)
5887                 {
5888                   if (size)
5889                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5890                   else if (ifx)
5891                     continueIfTrue (ifx);
5892                   goto release;
5893                 }
5894               emitcode ("setb", "c");
5895             }
5896           else
5897             {
5898               // lit == (0 or 1)
5899               if (lit == 0)
5900                 {
5901                   // lit == 0, result = left
5902                   if (size && sameRegs (AOP (result), AOP (left)))
5903                     goto release;
5904                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5905                 }
5906               else
5907                 {
5908                   // lit == 1, result = not(left)
5909                   if (size && sameRegs (AOP (result), AOP (left)))
5910                     {
5911                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5912                       goto release;
5913                     }
5914                   else
5915                     {
5916                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5917                       emitcode ("cpl", "c");
5918                     }
5919                 }
5920             }
5921
5922         }
5923       else
5924         {
5925           // right != literal
5926           symbol *tlbl = newiTempLabel (NULL);
5927           if (AOP_TYPE (right) == AOP_CRY)
5928             {
5929               // c = bit ^ bit;
5930               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5931             }
5932           else
5933             {
5934               int sizer = AOP_SIZE (right);
5935               // c = bit ^ val
5936               // if val>>1 != 0, result = 1
5937               emitcode ("setb", "c");
5938               while (sizer)
5939                 {
5940                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5941                   if (sizer == 1)
5942                     // test the msb of the lsb
5943                     emitcode ("anl", "a,#0xfe");
5944                   emitcode ("jnz", "%05d$", tlbl->key + 100);
5945                   sizer--;
5946                 }
5947               // val = (0,1)
5948               emitcode ("rrc", "a");
5949             }
5950           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5951           emitcode ("cpl", "c");
5952           emitcode ("", "%05d$:", (tlbl->key + 100));
5953         }
5954       // bit = c
5955       // val = c
5956       if (size)
5957         outBitC (result);
5958       // if(bit | ...)
5959       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5960         genIfxJump (ifx, "c");
5961       goto release;
5962     }
5963
5964   if (sameRegs (AOP (result), AOP (left)))
5965     {
5966       /* if left is same as result */
5967       for (; size--; offset++)
5968         {
5969           if (AOP_TYPE (right) == AOP_LIT)
5970             {
5971               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5972                 continue;
5973               else if (IS_AOP_PREG (left))
5974                 {
5975                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5976                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5977                   aopPut (AOP (result), "a", offset);
5978                 }
5979               else
5980                 emitcode ("xrl", "%s,%s",
5981                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5982                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5983             }
5984           else
5985             {
5986               if (AOP_TYPE (left) == AOP_ACC)
5987                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5988               else
5989                 {
5990                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5991                   if (IS_AOP_PREG (left))
5992                     {
5993                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5994                       aopPut (AOP (result), "a", offset);
5995                     }
5996                   else
5997                     emitcode ("xrl", "%s,a",
5998                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5999                 }
6000             }
6001         }
6002     }
6003   else
6004     {
6005       // left & result in different registers
6006       if (AOP_TYPE (result) == AOP_CRY)
6007         {
6008           // result = bit
6009           // if(size), result in bit
6010           // if(!size && ifx), conditional oper: if(left ^ right)
6011           symbol *tlbl = newiTempLabel (NULL);
6012           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6013           if (size)
6014             emitcode ("setb", "c");
6015           while (sizer--)
6016             {
6017               if ((AOP_TYPE (right) == AOP_LIT) &&
6018                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6019                 {
6020                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6021                 }
6022               else
6023                 {
6024                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6025                     emitcode ("xrl", "a,%s",
6026                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6027                   } else {
6028                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6029                     emitcode ("xrl", "a,%s",
6030                               aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6031                   }
6032                 }
6033               emitcode ("jnz", "%05d$", tlbl->key + 100);
6034               offset++;
6035             }
6036           if (size)
6037             {
6038               CLRC;
6039               emitcode ("", "%05d$:", tlbl->key + 100);
6040               outBitC (result);
6041             }
6042           else if (ifx)
6043             jmpTrueOrFalse (ifx, tlbl);
6044         }
6045       else
6046         for (; (size--); offset++)
6047           {
6048             // normal case
6049             // result = left & right
6050             if (AOP_TYPE (right) == AOP_LIT)
6051               {
6052                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6053                   {
6054                     aopPut (AOP (result),
6055                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6056                             offset);
6057                     continue;
6058                   }
6059                 D (emitcode (";", "better literal XOR.");
6060                   );
6061                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6062                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6063                                                   FALSE, FALSE, FALSE));
6064               }
6065             else
6066               {
6067                 // faster than result <- left, anl result,right
6068                 // and better if result is SFR
6069                 if (AOP_TYPE (left) == AOP_ACC)
6070                   {
6071                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6072                                                      FALSE, FALSE, FALSE));
6073                   }
6074                 else
6075                   {
6076                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6077                     emitcode ("xrl", "a,%s",
6078                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6079                   }
6080               }
6081             aopPut (AOP (result), "a", offset);
6082           }
6083     }
6084
6085 release:
6086   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6087   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6088   freeAsmop (result, NULL, ic, TRUE);
6089 }
6090
6091 /*-----------------------------------------------------------------*/
6092 /* genInline - write the inline code out                           */
6093 /*-----------------------------------------------------------------*/
6094 static void
6095 genInline (iCode * ic)
6096 {
6097   char *buffer, *bp, *bp1;
6098
6099   D (emitcode (";", "genInline ");
6100     );
6101
6102   _G.inLine += (!options.asmpeep);
6103
6104   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6105   strcpy (buffer, IC_INLINE (ic));
6106
6107   /* emit each line as a code */
6108   while (*bp)
6109     {
6110       if (*bp == '\n')
6111         {
6112           *bp++ = '\0';
6113           emitcode (bp1, "");
6114           bp1 = bp;
6115         }
6116       else
6117         {
6118           if (*bp == ':')
6119             {
6120               bp++;
6121               *bp = '\0';
6122               bp++;
6123               emitcode (bp1, "");
6124               bp1 = bp;
6125             }
6126           else
6127             bp++;
6128         }
6129     }
6130   if (bp1 != bp)
6131     emitcode (bp1, "");
6132   /*     emitcode("",buffer); */
6133   _G.inLine -= (!options.asmpeep);
6134 }
6135
6136 /*-----------------------------------------------------------------*/
6137 /* genRRC - rotate right with carry                                */
6138 /*-----------------------------------------------------------------*/
6139 static void
6140 genRRC (iCode * ic)
6141 {
6142   operand *left, *result;
6143   int size, offset = 0;
6144   char *l;
6145
6146   D (emitcode (";", "genRRC ");
6147     );
6148
6149   /* rotate right with carry */
6150   left = IC_LEFT (ic);
6151   result = IC_RESULT (ic);
6152   aopOp (left, ic, FALSE, FALSE);
6153   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6154
6155   /* move it to the result */
6156   size = AOP_SIZE (result);
6157   offset = size - 1;
6158   CLRC;
6159
6160   _startLazyDPSEvaluation ();
6161   while (size--)
6162     {
6163       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6164       MOVA (l);
6165       emitcode ("rrc", "a");
6166       if (AOP_SIZE (result) > 1)
6167         aopPut (AOP (result), "a", offset--);
6168     }
6169   _endLazyDPSEvaluation ();
6170
6171   /* now we need to put the carry into the
6172      highest order byte of the result */
6173   if (AOP_SIZE (result) > 1)
6174     {
6175       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6176       MOVA (l);
6177     }
6178   emitcode ("mov", "acc.7,c");
6179   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6180   freeAsmop (left, NULL, ic, TRUE);
6181   freeAsmop (result, NULL, ic, TRUE);
6182 }
6183
6184 /*-----------------------------------------------------------------*/
6185 /* genRLC - generate code for rotate left with carry               */
6186 /*-----------------------------------------------------------------*/
6187 static void
6188 genRLC (iCode * ic)
6189 {
6190   operand *left, *result;
6191   int size, offset = 0;
6192   char *l;
6193
6194   D (emitcode (";", "genRLC ");
6195     );
6196
6197   /* rotate right with carry */
6198   left = IC_LEFT (ic);
6199   result = IC_RESULT (ic);
6200   aopOp (left, ic, FALSE, FALSE);
6201   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6202
6203   /* move it to the result */
6204   size = AOP_SIZE (result);
6205   offset = 0;
6206   if (size--)
6207     {
6208       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6209       MOVA (l);
6210       emitcode ("add", "a,acc");
6211       if (AOP_SIZE (result) > 1)
6212         {
6213           aopPut (AOP (result), "a", offset++);
6214         }
6215
6216       _startLazyDPSEvaluation ();
6217       while (size--)
6218         {
6219           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6220           MOVA (l);
6221           emitcode ("rlc", "a");
6222           if (AOP_SIZE (result) > 1)
6223             aopPut (AOP (result), "a", offset++);
6224         }
6225       _endLazyDPSEvaluation ();
6226     }
6227   /* now we need to put the carry into the
6228      highest order byte of the result */
6229   if (AOP_SIZE (result) > 1)
6230     {
6231       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6232       MOVA (l);
6233     }
6234   emitcode ("mov", "acc.0,c");
6235   aopPut (AOP (result), "a", 0);
6236   freeAsmop (left, NULL, ic, TRUE);
6237   freeAsmop (result, NULL, ic, TRUE);
6238 }
6239
6240 /*-----------------------------------------------------------------*/
6241 /* genGetHbit - generates code get highest order bit               */
6242 /*-----------------------------------------------------------------*/
6243 static void
6244 genGetHbit (iCode * ic)
6245 {
6246   operand *left, *result;
6247   left = IC_LEFT (ic);
6248   result = IC_RESULT (ic);
6249   aopOp (left, ic, FALSE, FALSE);
6250   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6251
6252   D (emitcode (";", "genGetHbit ");
6253     );
6254
6255   /* get the highest order byte into a */
6256   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6257   if (AOP_TYPE (result) == AOP_CRY)
6258     {
6259       emitcode ("rlc", "a");
6260       outBitC (result);
6261     }
6262   else
6263     {
6264       emitcode ("rl", "a");
6265       emitcode ("anl", "a,#0x01");
6266       outAcc (result);
6267     }
6268
6269
6270   freeAsmop (left, NULL, ic, TRUE);
6271   freeAsmop (result, NULL, ic, TRUE);
6272 }
6273
6274 /*-----------------------------------------------------------------*/
6275 /* AccRol - rotate left accumulator by known count                 */
6276 /*-----------------------------------------------------------------*/
6277 static void
6278 AccRol (int shCount)
6279 {
6280   shCount &= 0x0007;            // shCount : 0..7
6281
6282   switch (shCount)
6283     {
6284     case 0:
6285       break;
6286     case 1:
6287       emitcode ("rl", "a");
6288       break;
6289     case 2:
6290       emitcode ("rl", "a");
6291       emitcode ("rl", "a");
6292       break;
6293     case 3:
6294       emitcode ("swap", "a");
6295       emitcode ("rr", "a");
6296       break;
6297     case 4:
6298       emitcode ("swap", "a");
6299       break;
6300     case 5:
6301       emitcode ("swap", "a");
6302       emitcode ("rl", "a");
6303       break;
6304     case 6:
6305       emitcode ("rr", "a");
6306       emitcode ("rr", "a");
6307       break;
6308     case 7:
6309       emitcode ("rr", "a");
6310       break;
6311     }
6312 }
6313
6314 /*-----------------------------------------------------------------*/
6315 /* AccLsh - left shift accumulator by known count                  */
6316 /*-----------------------------------------------------------------*/
6317 static void
6318 AccLsh (int shCount)
6319 {
6320   if (shCount != 0)
6321     {
6322       if (shCount == 1)
6323         emitcode ("add", "a,acc");
6324       else if (shCount == 2)
6325         {
6326           emitcode ("add", "a,acc");
6327           emitcode ("add", "a,acc");
6328         }
6329       else
6330         {
6331           /* rotate left accumulator */
6332           AccRol (shCount);
6333           /* and kill the lower order bits */
6334           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6335         }
6336     }
6337 }
6338
6339 /*-----------------------------------------------------------------*/
6340 /* AccRsh - right shift accumulator by known count                 */
6341 /*-----------------------------------------------------------------*/
6342 static void
6343 AccRsh (int shCount)
6344 {
6345   if (shCount != 0)
6346     {
6347       if (shCount == 1)
6348         {
6349           CLRC;
6350           emitcode ("rrc", "a");
6351         }
6352       else
6353         {
6354           /* rotate right accumulator */
6355           AccRol (8 - shCount);
6356           /* and kill the higher order bits */
6357           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6358         }
6359     }
6360 }
6361
6362 #ifdef BETTER_LITERAL_SHIFT
6363 /*-----------------------------------------------------------------*/
6364 /* AccSRsh - signed right shift accumulator by known count                 */
6365 /*-----------------------------------------------------------------*/
6366 static void
6367 AccSRsh (int shCount)
6368 {
6369   symbol *tlbl;
6370   if (shCount != 0)
6371     {
6372       if (shCount == 1)
6373         {
6374           emitcode ("mov", "c,acc.7");
6375           emitcode ("rrc", "a");
6376         }
6377       else if (shCount == 2)
6378         {
6379           emitcode ("mov", "c,acc.7");
6380           emitcode ("rrc", "a");
6381           emitcode ("mov", "c,acc.7");
6382           emitcode ("rrc", "a");
6383         }
6384       else
6385         {
6386           tlbl = newiTempLabel (NULL);
6387           /* rotate right accumulator */
6388           AccRol (8 - shCount);
6389           /* and kill the higher order bits */
6390           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6391           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6392           emitcode ("orl", "a,#0x%02x",
6393                     (unsigned char) ~SRMask[shCount]);
6394           emitcode ("", "%05d$:", tlbl->key + 100);
6395         }
6396     }
6397 }
6398 #endif
6399
6400 #ifdef BETTER_LITERAL_SHIFT
6401 /*-----------------------------------------------------------------*/
6402 /* shiftR1Left2Result - shift right one byte from left to result   */
6403 /*-----------------------------------------------------------------*/
6404 static void
6405 shiftR1Left2Result (operand * left, int offl,
6406                     operand * result, int offr,
6407                     int shCount, int sign)
6408 {
6409   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6410   /* shift right accumulator */
6411   if (sign)
6412     AccSRsh (shCount);
6413   else
6414     AccRsh (shCount);
6415   aopPut (AOP (result), "a", offr);
6416 }
6417 #endif
6418
6419 #ifdef BETTER_LITERAL_SHIFT
6420 /*-----------------------------------------------------------------*/
6421 /* shiftL1Left2Result - shift left one byte from left to result    */
6422 /*-----------------------------------------------------------------*/
6423 static void
6424 shiftL1Left2Result (operand * left, int offl,
6425                     operand * result, int offr, int shCount)
6426 {
6427   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6428   /* shift left accumulator */
6429   AccLsh (shCount);
6430   aopPut (AOP (result), "a", offr);
6431 }
6432 #endif
6433
6434 #ifdef BETTER_LITERAL_SHIFT
6435 /*-----------------------------------------------------------------*/
6436 /* movLeft2Result - move byte from left to result                  */
6437 /*-----------------------------------------------------------------*/
6438 static void
6439 movLeft2Result (operand * left, int offl,
6440                 operand * result, int offr, int sign)
6441 {
6442   char *l;
6443   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6444   {
6445       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6446
6447       if (*l == '@' && (IS_AOP_PREG (result)))
6448       {
6449           emitcode ("mov", "a,%s", l);
6450           aopPut (AOP (result), "a", offr);
6451       }
6452       else
6453       {
6454           if (!sign)
6455           {
6456             aopPut (AOP (result), l, offr);
6457           }
6458           else
6459             {
6460               /* MSB sign in acc.7 ! */
6461               if (getDataSize (left) == offl + 1)
6462                 {
6463                   emitcode ("mov", "a,%s", l);
6464                   aopPut (AOP (result), "a", offr);
6465                 }
6466             }
6467       }
6468   }
6469 }
6470 #endif
6471
6472 #ifdef BETTER_LITERAL_SHIFT
6473 /*-----------------------------------------------------------------*/
6474 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6475 /*-----------------------------------------------------------------*/
6476 static void
6477 AccAXRrl1 (char *x)
6478 {
6479   emitcode ("rrc", "a");
6480   emitcode ("xch", "a,%s", x);
6481   emitcode ("rrc", "a");
6482   emitcode ("xch", "a,%s", x);
6483 }
6484 #endif
6485
6486 #ifdef BETTER_LITERAL_SHIFT
6487 //REMOVE ME!!!
6488 /*-----------------------------------------------------------------*/
6489 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6490 /*-----------------------------------------------------------------*/
6491 static void
6492 AccAXLrl1 (char *x)
6493 {
6494   emitcode ("xch", "a,%s", x);
6495   emitcode ("rlc", "a");
6496   emitcode ("xch", "a,%s", x);
6497   emitcode ("rlc", "a");
6498 }
6499 #endif
6500
6501 #ifdef BETTER_LITERAL_SHIFT
6502 /*-----------------------------------------------------------------*/
6503 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6504 /*-----------------------------------------------------------------*/
6505 static void
6506 AccAXLsh1 (char *x)
6507 {
6508   emitcode ("xch", "a,%s", x);
6509   emitcode ("add", "a,acc");
6510   emitcode ("xch", "a,%s", x);
6511   emitcode ("rlc", "a");
6512 }
6513 #endif
6514
6515 #ifdef BETTER_LITERAL_SHIFT
6516 /*-----------------------------------------------------------------*/
6517 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6518 /*-----------------------------------------------------------------*/
6519 static void
6520 AccAXLsh (char *x, int shCount)
6521 {
6522   switch (shCount)
6523     {
6524     case 0:
6525       break;
6526     case 1:
6527       AccAXLsh1 (x);
6528       break;
6529     case 2:
6530       AccAXLsh1 (x);
6531       AccAXLsh1 (x);
6532       break;
6533     case 3:
6534     case 4:
6535     case 5:                     // AAAAABBB:CCCCCDDD
6536
6537       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
6538
6539       emitcode ("anl", "a,#0x%02x",
6540                 SLMask[shCount]);       // BBB00000:CCCCCDDD
6541
6542       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
6543
6544       AccRol (shCount);         // DDDCCCCC:BBB00000
6545
6546       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
6547
6548       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
6549
6550       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
6551
6552       emitcode ("anl", "a,#0x%02x",
6553                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
6554
6555       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
6556
6557       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
6558
6559       break;
6560     case 6:                     // AAAAAABB:CCCCCCDD
6561       emitcode ("anl", "a,#0x%02x",
6562                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6563       emitcode ("mov", "c,acc.0");      // c = B
6564       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6565 #if 0
6566       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6567       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6568 #else
6569       emitcode("rrc","a"); 
6570       emitcode("xch","a,%s", x); 
6571       emitcode("rrc","a"); 
6572       emitcode("mov","c,acc.0"); //<< get correct bit 
6573       emitcode("xch","a,%s", x); 
6574
6575       emitcode("rrc","a"); 
6576       emitcode("xch","a,%s", x); 
6577       emitcode("rrc","a"); 
6578       emitcode("xch","a,%s", x); 
6579 #endif
6580       break;
6581     case 7:                     // a:x <<= 7
6582
6583       emitcode ("anl", "a,#0x%02x",
6584                 SRMask[shCount]);       // 0000000B:CCCCCCCD
6585
6586       emitcode ("mov", "c,acc.0");      // c = B
6587
6588       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
6589
6590       AccAXRrl1 (x);            // BCCCCCCC:D0000000
6591
6592       break;
6593     default:
6594       break;
6595     }
6596 }
6597 #endif
6598
6599 #ifdef BETTER_LITERAL_SHIFT
6600 //REMOVE ME!!!
6601 /*-----------------------------------------------------------------*/
6602 /* AccAXRsh - right shift a:x known count (0..7)                   */
6603 /*-----------------------------------------------------------------*/
6604 static void
6605 AccAXRsh (char *x, int shCount)
6606 {
6607   switch (shCount)
6608     {
6609     case 0:
6610       break;
6611     case 1:
6612       CLRC;
6613       AccAXRrl1 (x);            // 0->a:x
6614
6615       break;
6616     case 2:
6617       CLRC;
6618       AccAXRrl1 (x);            // 0->a:x
6619
6620       CLRC;
6621       AccAXRrl1 (x);            // 0->a:x
6622
6623       break;
6624     case 3:
6625     case 4:
6626     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6627
6628       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
6629
6630       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6631
6632       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6633
6634       emitcode ("anl", "a,#0x%02x",
6635                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6636
6637       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6638
6639       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6640
6641       emitcode ("anl", "a,#0x%02x",
6642                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6643
6644       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6645
6646       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6647
6648       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
6649
6650       break;
6651     case 6:                     // AABBBBBB:CCDDDDDD
6652
6653       emitcode ("mov", "c,acc.7");
6654       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6655
6656       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6657
6658       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6659
6660       emitcode ("anl", "a,#0x%02x",
6661                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6662
6663       break;
6664     case 7:                     // ABBBBBBB:CDDDDDDD
6665
6666       emitcode ("mov", "c,acc.7");      // c = A
6667
6668       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6669
6670       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6671
6672       emitcode ("anl", "a,#0x%02x",
6673                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6674
6675       break;
6676     default:
6677       break;
6678     }
6679 }
6680 #endif
6681
6682 #ifdef BETTER_LITERAL_SHIFT
6683 /*-----------------------------------------------------------------*/
6684 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6685 /*-----------------------------------------------------------------*/
6686 static void
6687 AccAXRshS (char *x, int shCount)
6688 {
6689   symbol *tlbl;
6690   switch (shCount)
6691     {
6692     case 0:
6693       break;
6694     case 1:
6695       emitcode ("mov", "c,acc.7");
6696       AccAXRrl1 (x);            // s->a:x
6697
6698       break;
6699     case 2:
6700       emitcode ("mov", "c,acc.7");
6701       AccAXRrl1 (x);            // s->a:x
6702
6703       emitcode ("mov", "c,acc.7");
6704       AccAXRrl1 (x);            // s->a:x
6705
6706       break;
6707     case 3:
6708     case 4:
6709     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6710
6711       tlbl = newiTempLabel (NULL);
6712       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
6713
6714       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6715
6716       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6717
6718       emitcode ("anl", "a,#0x%02x",
6719                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6720
6721       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6722
6723       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6724
6725       emitcode ("anl", "a,#0x%02x",
6726                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6727
6728       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6729
6730       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6731
6732       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
6733
6734       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6735       emitcode ("orl", "a,#0x%02x",
6736                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
6737
6738       emitcode ("", "%05d$:", tlbl->key + 100);
6739       break;                    // SSSSAAAA:BBBCCCCC
6740
6741     case 6:                     // AABBBBBB:CCDDDDDD
6742
6743       tlbl = newiTempLabel (NULL);
6744       emitcode ("mov", "c,acc.7");
6745       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6746
6747       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6748
6749       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6750
6751       emitcode ("anl", "a,#0x%02x",
6752                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6753
6754       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6755       emitcode ("orl", "a,#0x%02x",
6756                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
6757
6758       emitcode ("", "%05d$:", tlbl->key + 100);
6759       break;
6760     case 7:                     // ABBBBBBB:CDDDDDDD
6761
6762       tlbl = newiTempLabel (NULL);
6763       emitcode ("mov", "c,acc.7");      // c = A
6764
6765       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6766
6767       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6768
6769       emitcode ("anl", "a,#0x%02x",
6770                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6771
6772       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6773       emitcode ("orl", "a,#0x%02x",
6774                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
6775
6776       emitcode ("", "%05d$:", tlbl->key + 100);
6777       break;
6778     default:
6779       break;
6780     }
6781 }
6782 #endif
6783
6784 #ifdef BETTER_LITERAL_SHIFT
6785 static void
6786 _loadLeftIntoAx(char    **lsb, 
6787                 operand *left, 
6788                 operand *result,
6789                 int     offl,
6790                 int     offr)
6791 {
6792   // Get the initial value from left into a pair of registers.
6793   // MSB must be in A, LSB can be any register.
6794   //
6795   // If the result is held in registers, it is an optimization
6796   // if the LSB can be held in the register which will hold the,
6797   // result LSB since this saves us from having to copy it into
6798   // the result following AccAXLsh.
6799   //
6800   // If the result is addressed indirectly, this is not a gain.
6801   if (AOP_NEEDSACC(result))
6802   {
6803        char *leftByte;
6804        
6805        _startLazyDPSEvaluation();
6806       if (AOP_TYPE(left) == AOP_DPTR2)
6807        {
6808            // Get MSB in A.
6809            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6810            // get LSB in DP2_RESULT_REG.
6811            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6812            assert(!strcmp(leftByte, DP2_RESULT_REG));
6813        }
6814        else
6815        {
6816            // get LSB into DP2_RESULT_REG
6817            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6818            if (strcmp(leftByte, DP2_RESULT_REG))
6819            {
6820                TR_AP("#7");
6821                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6822            }
6823            // And MSB in A.
6824            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6825            assert(strcmp(leftByte, DP2_RESULT_REG));
6826            MOVA(leftByte);
6827        }
6828        _endLazyDPSEvaluation();
6829        *lsb = DP2_RESULT_REG;
6830   }
6831   else
6832   {
6833       if (sameRegs (AOP (result), AOP (left)) &&
6834         ((offl + MSB16) == offr))
6835       {
6836           /* don't crash result[offr] */
6837           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6838           emitcode ("xch", "a,%s", 
6839                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6840       }
6841       else
6842       {
6843           movLeft2Result (left, offl, result, offr, 0);
6844           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6845       }
6846       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6847       assert(strcmp(*lsb,"a"));      
6848   }
6849 }
6850
6851 static void
6852 _storeAxResults(char    *lsb,
6853                 operand *result,
6854                 int     offr)
6855 {
6856   _startLazyDPSEvaluation();
6857   if (AOP_NEEDSACC(result))
6858   {
6859       /* We have to explicitly update the result LSB.
6860        */
6861       emitcode("xch","a,%s", lsb);
6862       aopPut(AOP(result), "a", offr);
6863       emitcode("mov","a,%s", lsb);
6864   }
6865   if (getDataSize (result) > 1)
6866   {
6867       aopPut (AOP (result), "a", offr + MSB16);
6868   }
6869   _endLazyDPSEvaluation();
6870 }
6871
6872 /*-----------------------------------------------------------------*/
6873 /* shiftL2Left2Result - shift left two bytes from left to result   */
6874 /*-----------------------------------------------------------------*/
6875 static void
6876 shiftL2Left2Result (operand * left, int offl,
6877                     operand * result, int offr, int shCount)
6878 {
6879   char *lsb;
6880
6881   _loadLeftIntoAx(&lsb, left, result, offl, offr);
6882   
6883   AccAXLsh (lsb, shCount);
6884   
6885   _storeAxResults(lsb, result, offr);
6886 }
6887 #endif
6888
6889 #ifdef BETTER_LITERAL_SHIFT
6890 /*-----------------------------------------------------------------*/
6891 /* shiftR2Left2Result - shift right two bytes from left to result  */
6892 /*-----------------------------------------------------------------*/
6893 static void
6894 shiftR2Left2Result (operand * left, int offl,
6895                     operand * result, int offr,
6896                     int shCount, int sign)
6897 {
6898   char *lsb;
6899   
6900   _loadLeftIntoAx(&lsb, left, result, offl, offr);
6901   
6902   /* a:x >> shCount (x = lsb(result)) */
6903   if (sign)
6904   {
6905      AccAXRshS(lsb, shCount);
6906   }
6907   else
6908   {
6909     AccAXRsh(lsb, shCount);
6910   }
6911   
6912   _storeAxResults(lsb, result, offr);
6913 }
6914 #endif
6915
6916 #if 0
6917 //REMOVE ME!!!
6918 /*-----------------------------------------------------------------*/
6919 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6920 /*-----------------------------------------------------------------*/
6921 static void
6922 shiftLLeftOrResult (operand * left, int offl,
6923                     operand * result, int offr, int shCount)
6924 {
6925   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6926   /* shift left accumulator */
6927   AccLsh (shCount);
6928   /* or with result */
6929   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6930   /* back to result */
6931   aopPut (AOP (result), "a", offr);
6932 }
6933 #endif
6934
6935 #if 0
6936 //REMOVE ME!!!
6937 /*-----------------------------------------------------------------*/
6938 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6939 /*-----------------------------------------------------------------*/
6940 static void
6941 shiftRLeftOrResult (operand * left, int offl,
6942                     operand * result, int offr, int shCount)
6943 {
6944   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6945   /* shift right accumulator */
6946   AccRsh (shCount);
6947   /* or with result */
6948   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6949   /* back to result */
6950   aopPut (AOP (result), "a", offr);
6951 }
6952 #endif
6953
6954 #ifdef BETTER_LITERAL_SHIFT
6955 /*-----------------------------------------------------------------*/
6956 /* genlshOne - left shift a one byte quantity by known count       */
6957 /*-----------------------------------------------------------------*/
6958 static void
6959 genlshOne (operand * result, operand * left, int shCount)
6960 {
6961   D (emitcode (";", "genlshOne "););
6962   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6963 }
6964 #endif
6965
6966 #ifdef BETTER_LITERAL_SHIFT
6967 /*-----------------------------------------------------------------*/
6968 /* genlshTwo - left shift two bytes by known amount != 0           */
6969 /*-----------------------------------------------------------------*/
6970 static void
6971 genlshTwo (operand * result, operand * left, int shCount)
6972 {
6973   int size;
6974
6975   D (emitcode (";", "genlshTwo "););
6976
6977   size = getDataSize (result);
6978
6979   /* if shCount >= 8 */
6980   if (shCount >= 8)
6981   {
6982       shCount -= 8;
6983
6984       _startLazyDPSEvaluation();
6985
6986       if (size > 1)
6987         {
6988           if (shCount)
6989           {
6990             _endLazyDPSEvaluation();
6991             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6992             aopPut (AOP (result), zero, LSB);       
6993           }
6994           else
6995           {
6996             movLeft2Result (left, LSB, result, MSB16, 0);
6997             aopPut (AOP (result), zero, LSB);
6998             _endLazyDPSEvaluation();
6999           }
7000         }
7001         else
7002         {
7003           aopPut (AOP (result), zero, LSB);
7004           _endLazyDPSEvaluation();
7005         }
7006   }
7007
7008   /*  1 <= shCount <= 7 */
7009   else
7010     {
7011       if (size == 1)
7012       {
7013         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7014       }
7015       else
7016       {
7017         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7018       }
7019     }
7020 }
7021 #endif
7022
7023 #if 0
7024 //REMOVE ME!!!
7025 /*-----------------------------------------------------------------*/
7026 /* shiftLLong - shift left one long from left to result            */
7027 /* offl = LSB or MSB16                                             */
7028 /*-----------------------------------------------------------------*/
7029 static void
7030 shiftLLong (operand * left, operand * result, int offr)
7031 {
7032   char *l;
7033   int size = AOP_SIZE (result);
7034
7035   if (size >= LSB + offr)
7036     {
7037       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7038       MOVA (l);
7039       emitcode ("add", "a,acc");
7040       if (sameRegs (AOP (left), AOP (result)) &&
7041           size >= MSB16 + offr && offr != LSB)
7042         emitcode ("xch", "a,%s",
7043                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7044       else
7045         aopPut (AOP (result), "a", LSB + offr);
7046     }
7047
7048   if (size >= MSB16 + offr)
7049     {
7050       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7051         {
7052           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7053           MOVA (l);
7054         }
7055       emitcode ("rlc", "a");
7056       if (sameRegs (AOP (left), AOP (result)) &&
7057           size >= MSB24 + offr && offr != LSB)
7058         emitcode ("xch", "a,%s",
7059                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7060       else
7061         aopPut (AOP (result), "a", MSB16 + offr);
7062     }
7063
7064   if (size >= MSB24 + offr)
7065     {
7066       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7067         {
7068           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7069           MOVA (l);
7070         }
7071       emitcode ("rlc", "a");
7072       if (sameRegs (AOP (left), AOP (result)) &&
7073           size >= MSB32 + offr && offr != LSB)
7074         emitcode ("xch", "a,%s",
7075                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7076       else
7077         aopPut (AOP (result), "a", MSB24 + offr);
7078     }
7079
7080   if (size > MSB32 + offr)
7081     {
7082       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7083         {
7084           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7085           MOVA (l);
7086         }
7087       emitcode ("rlc", "a");
7088       aopPut (AOP (result), "a", MSB32 + offr);
7089     }
7090   if (offr != LSB)
7091     aopPut (AOP (result), zero, LSB);
7092 }
7093 #endif
7094
7095 #if 0
7096 //REMOVE ME!!!
7097 /*-----------------------------------------------------------------*/
7098 /* genlshFour - shift four byte by a known amount != 0             */
7099 /*-----------------------------------------------------------------*/
7100 static void
7101 genlshFour (operand * result, operand * left, int shCount)
7102 {
7103   int size;
7104
7105   D (emitcode (";", "genlshFour ");
7106     );
7107
7108   size = AOP_SIZE (result);
7109
7110   /* if shifting more that 3 bytes */
7111   if (shCount >= 24)
7112     {
7113       shCount -= 24;
7114       if (shCount)
7115         /* lowest order of left goes to the highest
7116            order of the destination */
7117         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7118       else
7119         movLeft2Result (left, LSB, result, MSB32, 0);
7120       aopPut (AOP (result), zero, LSB);
7121       aopPut (AOP (result), zero, MSB16);
7122       aopPut (AOP (result), zero, MSB24);
7123       return;
7124     }
7125
7126   /* more than two bytes */
7127   else if (shCount >= 16)
7128     {
7129       /* lower order two bytes goes to higher order two bytes */
7130       shCount -= 16;
7131       /* if some more remaining */
7132       if (shCount)
7133         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7134       else
7135         {
7136           movLeft2Result (left, MSB16, result, MSB32, 0);
7137           movLeft2Result (left, LSB, result, MSB24, 0);
7138         }
7139       aopPut (AOP (result), zero, MSB16);
7140       aopPut (AOP (result), zero, LSB);
7141       return;
7142     }
7143
7144   /* if more than 1 byte */
7145   else if (shCount >= 8)
7146     {
7147       /* lower order three bytes goes to higher order  three bytes */
7148       shCount -= 8;
7149       if (size == 2)
7150         {
7151           if (shCount)
7152             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7153           else
7154             movLeft2Result (left, LSB, result, MSB16, 0);
7155         }
7156       else
7157         {                       /* size = 4 */
7158           if (shCount == 0)
7159             {
7160               movLeft2Result (left, MSB24, result, MSB32, 0);
7161               movLeft2Result (left, MSB16, result, MSB24, 0);
7162               movLeft2Result (left, LSB, result, MSB16, 0);
7163               aopPut (AOP (result), zero, LSB);
7164             }
7165           else if (shCount == 1)
7166             shiftLLong (left, result, MSB16);
7167           else
7168             {
7169               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7170               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7171               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7172               aopPut (AOP (result), zero, LSB);
7173             }
7174         }
7175     }
7176
7177   /* 1 <= shCount <= 7 */
7178   else if (shCount <= 2)
7179     {
7180       shiftLLong (left, result, LSB);
7181       if (shCount == 2)
7182         shiftLLong (result, result, LSB);
7183     }
7184   /* 3 <= shCount <= 7, optimize */
7185   else
7186     {
7187       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7188       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7189       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7190     }
7191 }
7192 #endif
7193
7194 #ifdef BETTER_LITERAL_SHIFT
7195 /*-----------------------------------------------------------------*/
7196 /* genLeftShiftLiteral - left shifting by known count              */
7197 /*-----------------------------------------------------------------*/
7198 static bool
7199 genLeftShiftLiteral (operand * left,
7200                      operand * right,
7201                      operand * result,
7202                      iCode * ic)
7203 {
7204   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7205   int size;
7206
7207   size = getSize (operandType (result));
7208
7209   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7210
7211   /* We only handle certain easy cases so far. */
7212   if ((shCount != 0)
7213    && (shCount < (size * 8))
7214    && (size != 1)
7215    && (size != 2))
7216   {
7217       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7218       return FALSE;
7219   }
7220
7221   freeAsmop (right, NULL, ic, TRUE);
7222
7223   aopOp(left, ic, FALSE, FALSE);
7224   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7225
7226 #if 1 // debug spew
7227   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7228   {
7229         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7230         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7231         {
7232            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7233         }
7234   }
7235   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7236   {
7237         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7238         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7239         {
7240            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7241         }       
7242   }  
7243 #endif
7244   
7245 #if VIEW_SIZE
7246   emitcode ("; shift left ", "result %d, left %d", size,
7247             AOP_SIZE (left));
7248 #endif
7249
7250   /* I suppose that the left size >= result size */
7251   if (shCount == 0)
7252   {
7253         _startLazyDPSEvaluation();
7254         while (size--)
7255         {
7256           movLeft2Result (left, size, result, size, 0);
7257         }
7258         _endLazyDPSEvaluation();
7259   }
7260   else if (shCount >= (size * 8))
7261   {
7262     _startLazyDPSEvaluation();
7263     while (size--)
7264     {
7265       aopPut (AOP (result), zero, size);
7266     }
7267     _endLazyDPSEvaluation();
7268   }
7269   else
7270   {
7271       switch (size)
7272         {
7273         case 1:
7274           genlshOne (result, left, shCount);
7275           break;
7276
7277         case 2:
7278           genlshTwo (result, left, shCount);
7279           break;
7280 #if 0
7281         case 4:
7282           genlshFour (result, left, shCount);
7283           break;
7284 #endif
7285         default:
7286           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7287           break;
7288         }
7289     }
7290   freeAsmop (left, NULL, ic, TRUE);
7291   freeAsmop (result, NULL, ic, TRUE);
7292   return TRUE;
7293 }
7294 #endif
7295
7296 /*-----------------------------------------------------------------*/
7297 /* genLeftShift - generates code for left shifting                 */
7298 /*-----------------------------------------------------------------*/
7299 static void
7300 genLeftShift (iCode * ic)
7301 {
7302   operand *left, *right, *result;
7303   int size, offset;
7304   char *l;
7305   symbol *tlbl, *tlbl1;
7306
7307   D (emitcode (";", "genLeftShift "););
7308
7309   right = IC_RIGHT (ic);
7310   left = IC_LEFT (ic);
7311   result = IC_RESULT (ic);
7312
7313   aopOp (right, ic, FALSE, FALSE);
7314
7315
7316 #ifdef BETTER_LITERAL_SHIFT
7317   /* if the shift count is known then do it
7318      as efficiently as possible */
7319   if (AOP_TYPE (right) == AOP_LIT)
7320     {
7321       if (genLeftShiftLiteral (left, right, result, ic))
7322       {
7323         return;
7324       }
7325     }
7326 #endif
7327
7328   /* shift count is unknown then we have to form
7329      a loop get the loop count in B : Note: we take
7330      only the lower order byte since shifting
7331      more that 32 bits make no sense anyway, ( the
7332      largest size of an object can be only 32 bits ) */
7333
7334   if (AOP_TYPE (right) == AOP_LIT)
7335   {
7336       /* Really should be handled by genLeftShiftLiteral,
7337        * but since I'm too lazy to fix that today, at least we can make
7338        * some small improvement.
7339        */
7340        emitcode("mov", "b,#0x%02x",
7341                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7342   }
7343   else
7344   {
7345         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7346         emitcode ("inc", "b");
7347   }
7348   freeAsmop (right, NULL, ic, TRUE);
7349   aopOp (left, ic, FALSE, FALSE);
7350   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7351
7352   /* now move the left to the result if they are not the
7353      same */
7354   if (!sameRegs (AOP (left), AOP (result)) &&
7355       AOP_SIZE (result) > 1)
7356     {
7357
7358       size = AOP_SIZE (result);
7359       offset = 0;
7360       _startLazyDPSEvaluation ();
7361       while (size--)
7362         {
7363           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7364           if (*l == '@' && (IS_AOP_PREG (result)))
7365             {
7366
7367               emitcode ("mov", "a,%s", l);
7368               aopPut (AOP (result), "a", offset);
7369             }
7370           else
7371             aopPut (AOP (result), l, offset);
7372           offset++;
7373         }
7374       _endLazyDPSEvaluation ();
7375     }
7376
7377   tlbl = newiTempLabel (NULL);
7378   size = AOP_SIZE (result);
7379   offset = 0;
7380   tlbl1 = newiTempLabel (NULL);
7381
7382   /* if it is only one byte then */
7383   if (size == 1)
7384     {
7385       symbol *tlbl1 = newiTempLabel (NULL);
7386
7387       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7388       MOVA (l);
7389       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7390       emitcode ("", "%05d$:", tlbl->key + 100);
7391       emitcode ("add", "a,acc");
7392       emitcode ("", "%05d$:", tlbl1->key + 100);
7393       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7394       aopPut (AOP (result), "a", 0);
7395       goto release;
7396     }
7397
7398   reAdjustPreg (AOP (result));
7399
7400   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7401   emitcode ("", "%05d$:", tlbl->key + 100);
7402   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7403   MOVA (l);
7404   emitcode ("add", "a,acc");
7405   aopPut (AOP (result), "a", offset++);
7406   _startLazyDPSEvaluation ();
7407   while (--size)
7408     {
7409       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7410       MOVA (l);
7411       emitcode ("rlc", "a");
7412       aopPut (AOP (result), "a", offset++);
7413     }
7414   _endLazyDPSEvaluation ();
7415   reAdjustPreg (AOP (result));
7416
7417   emitcode ("", "%05d$:", tlbl1->key + 100);
7418   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7419 release:
7420   freeAsmop (left, NULL, ic, TRUE);
7421   freeAsmop (result, NULL, ic, TRUE);
7422 }
7423
7424 #ifdef BETTER_LITERAL_SHIFT
7425 /*-----------------------------------------------------------------*/
7426 /* genrshOne - right shift a one byte quantity by known count      */
7427 /*-----------------------------------------------------------------*/
7428 static void
7429 genrshOne (operand * result, operand * left,
7430            int shCount, int sign)
7431 {
7432   D (emitcode (";", "genrshOne"););
7433   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7434 }
7435 #endif
7436
7437 #ifdef BETTER_LITERAL_SHIFT
7438 /*-----------------------------------------------------------------*/
7439 /* genrshTwo - right shift two bytes by known amount != 0          */
7440 /*-----------------------------------------------------------------*/
7441 static void
7442 genrshTwo (operand * result, operand * left,
7443            int shCount, int sign)
7444 {
7445   D (emitcode (";", "genrshTwo"););
7446
7447   /* if shCount >= 8 */
7448   if (shCount >= 8)
7449     {
7450       shCount -= 8;
7451       _startLazyDPSEvaluation();
7452       if (shCount)
7453       {
7454         shiftR1Left2Result (left, MSB16, result, LSB,
7455                             shCount, sign);
7456       }                     
7457       else
7458       {
7459         movLeft2Result (left, MSB16, result, LSB, sign);
7460       }
7461       addSign (result, MSB16, sign);
7462       _endLazyDPSEvaluation();
7463     }
7464
7465   /*  1 <= shCount <= 7 */
7466   else
7467   {
7468     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7469   }
7470 }
7471 #endif
7472
7473 #if 0
7474 //REMOVE ME!!!
7475 /*-----------------------------------------------------------------*/
7476 /* shiftRLong - shift right one long from left to result           */
7477 /* offl = LSB or MSB16                                             */
7478 /*-----------------------------------------------------------------*/
7479 static void
7480 shiftRLong (operand * left, int offl,
7481             operand * result, int sign)
7482 {
7483   int isSameRegs=sameRegs(AOP(left),AOP(result));
7484
7485   if (isSameRegs && offl>1) {
7486     // we are in big trouble, but this shouldn't happen
7487     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7488   }
7489
7490   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7491   
7492   if (offl==MSB16) {
7493     // shift is > 8
7494     if (sign) {
7495       emitcode ("rlc", "a");
7496       emitcode ("subb", "a,acc");
7497       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7498     } else {
7499       aopPut (AOP(result), zero, MSB32);
7500     }
7501   }
7502
7503   if (!sign) {
7504     emitcode ("clr", "c");
7505   } else {
7506     emitcode ("mov", "c,acc.7");
7507   }
7508
7509   emitcode ("rrc", "a");
7510
7511   if (isSameRegs && offl==MSB16) {
7512     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7513   } else {
7514     aopPut (AOP (result), "a", MSB32);
7515     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7516   }
7517
7518   emitcode ("rrc", "a");
7519   if (isSameRegs && offl==1) {
7520     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7521   } else {
7522     aopPut (AOP (result), "a", MSB24);
7523     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7524   }
7525   emitcode ("rrc", "a");
7526   aopPut (AOP (result), "a", MSB16 - offl);
7527
7528   if (offl == LSB)
7529     {
7530       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7531       emitcode ("rrc", "a");
7532       aopPut (AOP (result), "a", LSB);
7533     }
7534 }
7535 #endif
7536
7537 #if 0
7538 //REMOVE ME!!!
7539 /*-----------------------------------------------------------------*/
7540 /* genrshFour - shift four byte by a known amount != 0             */
7541 /*-----------------------------------------------------------------*/
7542 static void
7543 genrshFour (operand * result, operand * left,
7544             int shCount, int sign)
7545 {
7546   D (emitcode (";", "genrshFour");
7547     );
7548
7549   /* if shifting more that 3 bytes */
7550   if (shCount >= 24)
7551     {
7552       shCount -= 24;
7553       if (shCount)
7554         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7555       else
7556         movLeft2Result (left, MSB32, result, LSB, sign);
7557       addSign (result, MSB16, sign);
7558     }
7559   else if (shCount >= 16)
7560     {
7561       shCount -= 16;
7562       if (shCount)
7563         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7564       else
7565         {
7566           movLeft2Result (left, MSB24, result, LSB, 0);
7567           movLeft2Result (left, MSB32, result, MSB16, sign);
7568         }
7569       addSign (result, MSB24, sign);
7570     }
7571   else if (shCount >= 8)
7572     {
7573       shCount -= 8;
7574       if (shCount == 1)
7575         shiftRLong (left, MSB16, result, sign);
7576       else if (shCount == 0)
7577         {
7578           movLeft2Result (left, MSB16, result, LSB, 0);
7579           movLeft2Result (left, MSB24, result, MSB16, 0);
7580           movLeft2Result (left, MSB32, result, MSB24, sign);
7581           addSign (result, MSB32, sign);
7582         }
7583       else
7584         {
7585           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7586           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7587           /* the last shift is signed */
7588           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7589           addSign (result, MSB32, sign);
7590         }
7591     }
7592   else
7593     {                           /* 1 <= shCount <= 7 */
7594       if (shCount <= 2)
7595         {
7596           shiftRLong (left, LSB, result, sign);
7597           if (shCount == 2)
7598             shiftRLong (result, LSB, result, sign);
7599         }
7600       else
7601         {
7602           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7603           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7604           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7605         }
7606     }
7607 }
7608 #endif
7609
7610 #ifdef BETTER_LITERAL_SHIFT
7611 /*-----------------------------------------------------------------*/
7612 /* genRightShiftLiteral - right shifting by known count            */
7613 /*-----------------------------------------------------------------*/
7614 static bool
7615 genRightShiftLiteral (operand * left,
7616                       operand * right,
7617                       operand * result,
7618                       iCode * ic,
7619                       int sign)
7620 {
7621   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7622   int size;
7623
7624   size = getSize (operandType (result));
7625
7626   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7627
7628   /* We only handle certain easy cases so far. */
7629   if ((shCount != 0)
7630    && (shCount < (size * 8))
7631    && (size != 1)
7632    && (size != 2))
7633   {
7634       D(emitcode (";", "genRightShiftLiteral wimping out"););   
7635       return FALSE;
7636   }
7637
7638   freeAsmop (right, NULL, ic, TRUE);
7639
7640   aopOp (left, ic, FALSE, FALSE);
7641   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7642
7643 #if VIEW_SIZE
7644   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7645             AOP_SIZE (left));
7646 #endif
7647
7648   /* test the LEFT size !!! */
7649
7650   /* I suppose that the left size >= result size */
7651   if (shCount == 0)
7652   {
7653       size = getDataSize (result);
7654       _startLazyDPSEvaluation();
7655       while (size--)
7656       {
7657         movLeft2Result (left, size, result, size, 0);
7658       }
7659       _endLazyDPSEvaluation();
7660   }
7661   else if (shCount >= (size * 8))
7662     {
7663       if (sign)
7664       {
7665         /* get sign in acc.7 */
7666         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7667       }
7668       addSign (result, LSB, sign);
7669     }
7670   else
7671     {
7672       switch (size)
7673         {
7674         case 1:
7675           genrshOne (result, left, shCount, sign);
7676           break;
7677
7678         case 2:
7679           genrshTwo (result, left, shCount, sign);
7680           break;
7681 #if 0
7682         case 4:
7683           genrshFour (result, left, shCount, sign);
7684           break;
7685 #endif    
7686         default:
7687           break;
7688         }
7689
7690       freeAsmop (left, NULL, ic, TRUE);
7691       freeAsmop (result, NULL, ic, TRUE);
7692     }
7693     return TRUE;
7694 }
7695 #endif
7696
7697 /*-----------------------------------------------------------------*/
7698 /* genSignedRightShift - right shift of signed number              */
7699 /*-----------------------------------------------------------------*/
7700 static void
7701 genSignedRightShift (iCode * ic)
7702 {
7703   operand *right, *left, *result;
7704   int size, offset;
7705   char *l;
7706   symbol *tlbl, *tlbl1;
7707
7708   D (emitcode (";", "genSignedRightShift "););
7709
7710   /* we do it the hard way put the shift count in b
7711      and loop thru preserving the sign */
7712
7713   right = IC_RIGHT (ic);
7714   left = IC_LEFT (ic);
7715   result = IC_RESULT (ic);
7716
7717   aopOp (right, ic, FALSE, FALSE);
7718
7719 #ifdef BETTER_LITERAL_SHIFT
7720   if (AOP_TYPE (right) == AOP_LIT)
7721     {
7722       if (genRightShiftLiteral (left, right, result, ic, 1))
7723       {
7724         return;
7725       }
7726     }
7727 #endif
7728   /* shift count is unknown then we have to form
7729      a loop get the loop count in B : Note: we take
7730      only the lower order byte since shifting
7731      more that 32 bits make no sense anyway, ( the
7732      largest size of an object can be only 32 bits ) */
7733
7734   if (AOP_TYPE (right) == AOP_LIT)
7735   {
7736       /* Really should be handled by genRightShiftLiteral,
7737        * but since I'm too lazy to fix that today, at least we can make
7738        * some small improvement.
7739        */
7740        emitcode("mov", "b,#0x%02x",
7741                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7742   }
7743   else
7744   {
7745         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7746         emitcode ("inc", "b");
7747   }
7748   freeAsmop (right, NULL, ic, TRUE);
7749   aopOp (left, ic, FALSE, FALSE);
7750   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7751
7752   /* now move the left to the result if they are not the
7753      same */
7754   if (!sameRegs (AOP (left), AOP (result)) &&
7755       AOP_SIZE (result) > 1)
7756     {
7757
7758       size = AOP_SIZE (result);
7759       offset = 0;
7760       _startLazyDPSEvaluation ();
7761       while (size--)
7762         {
7763           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7764           if (*l == '@' && IS_AOP_PREG (result))
7765             {
7766
7767               emitcode ("mov", "a,%s", l);
7768               aopPut (AOP (result), "a", offset);
7769             }
7770           else
7771             aopPut (AOP (result), l, offset);
7772           offset++;
7773         }
7774       _endLazyDPSEvaluation ();
7775     }
7776
7777   /* mov the highest order bit to OVR */
7778   tlbl = newiTempLabel (NULL);
7779   tlbl1 = newiTempLabel (NULL);
7780
7781   size = AOP_SIZE (result);
7782   offset = size - 1;
7783   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7784   emitcode ("rlc", "a");
7785   emitcode ("mov", "ov,c");
7786   /* if it is only one byte then */
7787   if (size == 1)
7788     {
7789       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7790       MOVA (l);
7791       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7792       emitcode ("", "%05d$:", tlbl->key + 100);
7793       emitcode ("mov", "c,ov");
7794       emitcode ("rrc", "a");
7795       emitcode ("", "%05d$:", tlbl1->key + 100);
7796       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7797       aopPut (AOP (result), "a", 0);
7798       goto release;
7799     }
7800
7801   reAdjustPreg (AOP (result));
7802   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7803   emitcode ("", "%05d$:", tlbl->key + 100);
7804   emitcode ("mov", "c,ov");
7805   _startLazyDPSEvaluation ();
7806   while (size--)
7807     {
7808       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7809       MOVA (l);
7810       emitcode ("rrc", "a");
7811       aopPut (AOP (result), "a", offset--);
7812     }
7813   _endLazyDPSEvaluation ();
7814   reAdjustPreg (AOP (result));
7815   emitcode ("", "%05d$:", tlbl1->key + 100);
7816   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7817
7818 release:
7819   freeAsmop (left, NULL, ic, TRUE);
7820   freeAsmop (result, NULL, ic, TRUE);
7821 }
7822
7823 /*-----------------------------------------------------------------*/
7824 /* genRightShift - generate code for right shifting                */
7825 /*-----------------------------------------------------------------*/
7826 static void
7827 genRightShift (iCode * ic)
7828 {
7829   operand *right, *left, *result;
7830   sym_link *retype;
7831   int size, offset;
7832   char *l;
7833   symbol *tlbl, *tlbl1;
7834
7835   D (emitcode (";", "genRightShift "););
7836
7837   /* if signed then we do it the hard way preserve the
7838      sign bit moving it inwards */
7839   retype = getSpec (operandType (IC_RESULT (ic)));
7840
7841   if (!SPEC_USIGN (retype))
7842     {
7843       genSignedRightShift (ic);
7844       return;
7845     }
7846
7847   /* signed & unsigned types are treated the same : i.e. the
7848      signed is NOT propagated inwards : quoting from the
7849      ANSI - standard : "for E1 >> E2, is equivalent to division
7850      by 2**E2 if unsigned or if it has a non-negative value,
7851      otherwise the result is implementation defined ", MY definition
7852      is that the sign does not get propagated */
7853
7854   right = IC_RIGHT (ic);
7855   left = IC_LEFT (ic);
7856   result = IC_RESULT (ic);
7857
7858   aopOp (right, ic, FALSE, FALSE);
7859
7860 #ifdef BETTER_LITERAL_SHIFT
7861   /* if the shift count is known then do it
7862      as efficiently as possible */
7863   if (AOP_TYPE (right) == AOP_LIT)
7864     {
7865       if (genRightShiftLiteral (left, right, result, ic, 0))
7866       {
7867         return;
7868       }
7869     }
7870 #endif
7871
7872   /* shift count is unknown then we have to form
7873      a loop get the loop count in B : Note: we take
7874      only the lower order byte since shifting
7875      more that 32 bits make no sense anyway, ( the
7876      largest size of an object can be only 32 bits ) */
7877   
7878   if (AOP_TYPE (right) == AOP_LIT)
7879   {
7880       /* Really should be handled by genRightShiftLiteral,
7881        * but since I'm too lazy to fix that today, at least we can make
7882        * some small improvement.
7883        */
7884        emitcode("mov", "b,#0x%02x",
7885                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7886   }
7887   else
7888   {
7889         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7890         emitcode ("inc", "b");
7891   }
7892   freeAsmop (right, NULL, ic, TRUE);
7893   aopOp (left, ic, FALSE, FALSE);
7894   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7895
7896   /* now move the left to the result if they are not the
7897      same */
7898   if (!sameRegs (AOP (left), AOP (result)) &&
7899       AOP_SIZE (result) > 1)
7900     {
7901
7902       size = AOP_SIZE (result);
7903       offset = 0;
7904       _startLazyDPSEvaluation ();
7905       while (size--)
7906         {
7907           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7908           if (*l == '@' && IS_AOP_PREG (result))
7909             {
7910
7911               emitcode ("mov", "a,%s", l);
7912               aopPut (AOP (result), "a", offset);
7913             }
7914           else
7915             aopPut (AOP (result), l, offset);
7916           offset++;
7917         }
7918       _endLazyDPSEvaluation ();
7919     }
7920
7921   tlbl = newiTempLabel (NULL);
7922   tlbl1 = newiTempLabel (NULL);
7923   size = AOP_SIZE (result);
7924   offset = size - 1;
7925
7926   /* if it is only one byte then */
7927   if (size == 1)
7928     {
7929       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7930       MOVA (l);
7931       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7932       emitcode ("", "%05d$:", tlbl->key + 100);
7933       CLRC;
7934       emitcode ("rrc", "a");
7935       emitcode ("", "%05d$:", tlbl1->key + 100);
7936       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7937       aopPut (AOP (result), "a", 0);
7938       goto release;
7939     }
7940
7941   reAdjustPreg (AOP (result));
7942   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7943   emitcode ("", "%05d$:", tlbl->key + 100);
7944   CLRC;
7945   _startLazyDPSEvaluation ();
7946   while (size--)
7947     {
7948       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7949       MOVA (l);
7950       emitcode ("rrc", "a");
7951       aopPut (AOP (result), "a", offset--);
7952     }
7953   _endLazyDPSEvaluation ();
7954   reAdjustPreg (AOP (result));
7955
7956   emitcode ("", "%05d$:", tlbl1->key + 100);
7957   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7958
7959 release:
7960   freeAsmop (left, NULL, ic, TRUE);
7961   freeAsmop (result, NULL, ic, TRUE);
7962 }
7963
7964 /*-----------------------------------------------------------------*/
7965 /* genUnpackBits - generates code for unpacking bits               */
7966 /*-----------------------------------------------------------------*/
7967 static void
7968 genUnpackBits (operand * result, char *rname, int ptype)
7969 {
7970   int shCnt;
7971   int rlen = 0;
7972   sym_link *etype;
7973   int offset = 0;
7974
7975   D (emitcode (";", "genUnpackBits ");
7976     );
7977
7978   etype = getSpec (operandType (result));
7979
7980   /* read the first byte  */
7981   switch (ptype)
7982     {
7983
7984     case POINTER:
7985     case IPOINTER:
7986       emitcode ("mov", "a,@%s", rname);
7987       break;
7988
7989     case PPOINTER:
7990       emitcode ("movx", "a,@%s", rname);
7991       break;
7992
7993     case FPOINTER:
7994       emitcode ("movx", "a,@dptr");
7995       break;
7996
7997     case CPOINTER:
7998       emitcode ("clr", "a");
7999       emitcode ("movc", "a,@a+dptr");
8000       break;
8001
8002     case GPOINTER:
8003       emitcode ("lcall", "__gptrget");
8004       break;
8005     }
8006
8007   /* if we have bitdisplacement then it fits   */
8008   /* into this byte completely or if length is */
8009   /* less than a byte                          */
8010   if ((shCnt = SPEC_BSTR (etype)) ||
8011       (SPEC_BLEN (etype) <= 8))
8012     {
8013
8014       /* shift right acc */
8015       AccRsh (shCnt);
8016
8017       emitcode ("anl", "a,#0x%02x",
8018                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8019       aopPut (AOP (result), "a", offset);
8020       return;
8021     }
8022
8023   /* bit field did not fit in a byte  */
8024   rlen = SPEC_BLEN (etype) - 8;
8025   aopPut (AOP (result), "a", offset++);
8026
8027   while (1)
8028     {
8029
8030       switch (ptype)
8031         {
8032         case POINTER:
8033         case IPOINTER:
8034           emitcode ("inc", "%s", rname);
8035           emitcode ("mov", "a,@%s", rname);
8036           break;
8037
8038         case PPOINTER:
8039           emitcode ("inc", "%s", rname);
8040           emitcode ("movx", "a,@%s", rname);
8041           break;
8042
8043         case FPOINTER:
8044           emitcode ("inc", "dptr");
8045           emitcode ("movx", "a,@dptr");
8046           break;
8047
8048         case CPOINTER:
8049           emitcode ("clr", "a");
8050           emitcode ("inc", "dptr");
8051           emitcode ("movc", "a,@a+dptr");
8052           break;
8053
8054         case GPOINTER:
8055           emitcode ("inc", "dptr");
8056           emitcode ("lcall", "__gptrget");
8057           break;
8058         }
8059
8060       rlen -= 8;
8061       /* if we are done */
8062       if (rlen < 8)
8063         break;
8064
8065       aopPut (AOP (result), "a", offset++);
8066
8067     }
8068
8069   if (rlen)
8070     {
8071       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8072       aopPut (AOP (result), "a", offset);
8073     }
8074
8075   return;
8076 }
8077
8078
8079 /*-----------------------------------------------------------------*/
8080 /* genDataPointerGet - generates code when ptr offset is known     */
8081 /*-----------------------------------------------------------------*/
8082 static void
8083 genDataPointerGet (operand * left,
8084                    operand * result,
8085                    iCode * ic)
8086 {
8087   char *l;
8088   char buffer[256];
8089   int size, offset = 0;
8090   aopOp (result, ic, TRUE, FALSE);
8091
8092   /* get the string representation of the name */
8093   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8094   size = AOP_SIZE (result);
8095   _startLazyDPSEvaluation ();
8096   while (size--)
8097     {
8098       if (offset)
8099         sprintf (buffer, "(%s + %d)", l + 1, offset);
8100       else
8101         sprintf (buffer, "%s", l + 1);
8102       aopPut (AOP (result), buffer, offset++);
8103     }
8104   _endLazyDPSEvaluation ();
8105
8106   freeAsmop (left, NULL, ic, TRUE);
8107   freeAsmop (result, NULL, ic, TRUE);
8108 }
8109
8110 /*-----------------------------------------------------------------*/
8111 /* genNearPointerGet - emitcode for near pointer fetch             */
8112 /*-----------------------------------------------------------------*/
8113 static void
8114 genNearPointerGet (operand * left,
8115                    operand * result,
8116                    iCode * ic)
8117 {
8118   asmop *aop = NULL;
8119   regs *preg = NULL;
8120   char *rname;
8121   sym_link *rtype, *retype, *letype;
8122   sym_link *ltype = operandType (left);
8123   char buffer[80];
8124
8125   rtype = operandType (result);
8126   retype = getSpec (rtype);
8127   letype = getSpec (ltype);
8128
8129   aopOp (left, ic, FALSE, FALSE);
8130
8131   /* if left is rematerialisable and
8132      result is not bit variable type and
8133      the left is pointer to data space i.e
8134      lower 128 bytes of space */
8135   if (AOP_TYPE (left) == AOP_IMMD &&
8136       !IS_BITVAR (retype) &&
8137       !IS_BITVAR (letype) &&
8138       DCL_TYPE (ltype) == POINTER)
8139     {
8140       genDataPointerGet (left, result, ic);
8141       return;
8142     }
8143
8144   /* if the value is already in a pointer register
8145      then don't need anything more */
8146   if (!AOP_INPREG (AOP (left)))
8147     {
8148       /* otherwise get a free pointer register */
8149       aop = newAsmop (0);
8150       preg = getFreePtr (ic, &aop, FALSE);
8151       emitcode ("mov", "%s,%s",
8152                 preg->name,
8153                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8154       rname = preg->name;
8155     }
8156   else
8157     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8158
8159   freeAsmop (left, NULL, ic, TRUE);
8160   aopOp (result, ic, FALSE, FALSE);
8161
8162   /* if bitfield then unpack the bits */
8163   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8164     genUnpackBits (result, rname, POINTER);
8165   else
8166     {
8167       /* we have can just get the values */
8168       int size = AOP_SIZE (result);
8169       int offset = 0;
8170
8171       while (size--)
8172         {
8173           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8174             {
8175
8176               emitcode ("mov", "a,@%s", rname);
8177               aopPut (AOP (result), "a", offset);
8178             }
8179           else
8180             {
8181               sprintf (buffer, "@%s", rname);
8182               aopPut (AOP (result), buffer, offset);
8183             }
8184           offset++;
8185           if (size)
8186             emitcode ("inc", "%s", rname);
8187         }
8188     }
8189
8190   /* now some housekeeping stuff */
8191   if (aop)
8192     {
8193       /* we had to allocate for this iCode */
8194       freeAsmop (NULL, aop, ic, TRUE);
8195     }
8196   else
8197     {
8198       /* we did not allocate which means left
8199          already in a pointer register, then
8200          if size > 0 && this could be used again
8201          we have to point it back to where it
8202          belongs */
8203       if (AOP_SIZE (result) > 1 &&
8204           !OP_SYMBOL (left)->remat &&
8205           (OP_SYMBOL (left)->liveTo > ic->seq ||
8206            ic->depth))
8207         {
8208           int size = AOP_SIZE (result) - 1;
8209           while (size--)
8210             emitcode ("dec", "%s", rname);
8211         }
8212     }
8213
8214   /* done */
8215   freeAsmop (result, NULL, ic, TRUE);
8216
8217 }
8218
8219 /*-----------------------------------------------------------------*/
8220 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8221 /*-----------------------------------------------------------------*/
8222 static void
8223 genPagedPointerGet (operand * left,
8224                     operand * result,
8225                     iCode * ic)
8226 {
8227   asmop *aop = NULL;
8228   regs *preg = NULL;
8229   char *rname;
8230   sym_link *rtype, *retype, *letype;
8231
8232   rtype = operandType (result);
8233   retype = getSpec (rtype);
8234   letype = getSpec (operandType (left));
8235   aopOp (left, ic, FALSE, FALSE);
8236
8237   /* if the value is already in a pointer register
8238      then don't need anything more */
8239   if (!AOP_INPREG (AOP (left)))
8240     {
8241       /* otherwise get a free pointer register */
8242       aop = newAsmop (0);
8243       preg = getFreePtr (ic, &aop, FALSE);
8244       emitcode ("mov", "%s,%s",
8245                 preg->name,
8246                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8247       rname = preg->name;
8248     }
8249   else
8250     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8251
8252   freeAsmop (left, NULL, ic, TRUE);
8253   aopOp (result, ic, FALSE, FALSE);
8254
8255   /* if bitfield then unpack the bits */
8256   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8257     genUnpackBits (result, rname, PPOINTER);
8258   else
8259     {
8260       /* we have can just get the values */
8261       int size = AOP_SIZE (result);
8262       int offset = 0;
8263
8264       while (size--)
8265         {
8266
8267           emitcode ("movx", "a,@%s", rname);
8268           aopPut (AOP (result), "a", offset);
8269
8270           offset++;
8271
8272           if (size)
8273             emitcode ("inc", "%s", rname);
8274         }
8275     }
8276
8277   /* now some housekeeping stuff */
8278   if (aop)
8279     {
8280       /* we had to allocate for this iCode */
8281       freeAsmop (NULL, aop, ic, TRUE);
8282     }
8283   else
8284     {
8285       /* we did not allocate which means left
8286          already in a pointer register, then
8287          if size > 0 && this could be used again
8288          we have to point it back to where it
8289          belongs */
8290       if (AOP_SIZE (result) > 1 &&
8291           !OP_SYMBOL (left)->remat &&
8292           (OP_SYMBOL (left)->liveTo > ic->seq ||
8293            ic->depth))
8294         {
8295           int size = AOP_SIZE (result) - 1;
8296           while (size--)
8297             emitcode ("dec", "%s", rname);
8298         }
8299     }
8300
8301   /* done */
8302   freeAsmop (result, NULL, ic, TRUE);
8303
8304
8305 }
8306
8307 /*-----------------------------------------------------------------*/
8308 /* genFarPointerGet - gget value from far space                    */
8309 /*-----------------------------------------------------------------*/
8310 static void
8311 genFarPointerGet (operand * left,
8312                   operand * result, iCode * ic)
8313 {
8314   int size, offset;
8315   sym_link *retype = getSpec (operandType (result));
8316   sym_link *letype = getSpec (operandType (left));
8317   D (emitcode (";", "genFarPointerGet");
8318     );
8319
8320   aopOp (left, ic, FALSE, FALSE);
8321
8322   /* if the operand is already in dptr
8323      then we do nothing else we move the value to dptr */
8324   if (AOP_TYPE (left) != AOP_STR)
8325     {
8326       /* if this is remateriazable */
8327       if (AOP_TYPE (left) == AOP_IMMD)
8328         {
8329           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8330         }
8331       else
8332         {
8333           /* we need to get it byte by byte */
8334           _startLazyDPSEvaluation ();
8335           if (AOP_TYPE (left) != AOP_DPTR)
8336             {
8337               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8338               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8339               if (options.model == MODEL_FLAT24)
8340                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8341             }
8342           else
8343             {
8344               /* We need to generate a load to DPTR indirect through DPTR. */
8345               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8346                 );
8347               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8348               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8349               if (options.model == MODEL_FLAT24)
8350                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8351               emitcode ("pop", "dph");
8352               emitcode ("pop", "dpl");
8353             }
8354           _endLazyDPSEvaluation ();
8355         }
8356     }
8357   /* so dptr know contains the address */
8358   freeAsmop (left, NULL, ic, TRUE);
8359   aopOp (result, ic, FALSE, TRUE);
8360
8361   /* if bit then unpack */
8362   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8363     genUnpackBits (result, "dptr", FPOINTER);
8364   else
8365     {
8366       size = AOP_SIZE (result);
8367       offset = 0;
8368
8369       _startLazyDPSEvaluation ();
8370       while (size--)
8371         {
8372
8373           genSetDPTR (0);
8374           _flushLazyDPS ();
8375
8376           emitcode ("movx", "a,@dptr");
8377           if (size)
8378             emitcode ("inc", "dptr");
8379
8380           aopPut (AOP (result), "a", offset++);
8381         }
8382       _endLazyDPSEvaluation ();
8383     }
8384
8385   freeAsmop (result, NULL, ic, TRUE);
8386 }
8387
8388 /*-----------------------------------------------------------------*/
8389 /* emitcodePointerGet - gget value from code space                  */
8390 /*-----------------------------------------------------------------*/
8391 static void
8392 emitcodePointerGet (operand * left,
8393                     operand * result, iCode * ic)
8394 {
8395   int size, offset;
8396   sym_link *retype = getSpec (operandType (result));
8397
8398   aopOp (left, ic, FALSE, FALSE);
8399
8400   /* if the operand is already in dptr
8401      then we do nothing else we move the value to dptr */
8402   if (AOP_TYPE (left) != AOP_STR)
8403     {
8404       /* if this is remateriazable */
8405       if (AOP_TYPE (left) == AOP_IMMD)
8406         {
8407           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8408         }
8409       else
8410         {                       /* we need to get it byte by byte */
8411           _startLazyDPSEvaluation ();
8412           if (AOP_TYPE (left) != AOP_DPTR)
8413             {
8414               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8415               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8416               if (options.model == MODEL_FLAT24)
8417                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8418             }
8419           else
8420             {
8421               /* We need to generate a load to DPTR indirect through DPTR. */
8422               D (emitcode (";", "gencodePointerGet -- indirection special case.");
8423                 );
8424               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8425               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8426               if (options.model == MODEL_FLAT24)
8427                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8428               emitcode ("pop", "dph");
8429               emitcode ("pop", "dpl");
8430             }
8431           _endLazyDPSEvaluation ();
8432         }
8433     }
8434   /* so dptr know contains the address */
8435   freeAsmop (left, NULL, ic, TRUE);
8436   aopOp (result, ic, FALSE, TRUE);
8437
8438   /* if bit then unpack */
8439   if (IS_BITVAR (retype))
8440     genUnpackBits (result, "dptr", CPOINTER);
8441   else
8442     {
8443       size = AOP_SIZE (result);
8444       offset = 0;
8445
8446       _startLazyDPSEvaluation ();
8447       while (size--)
8448         {
8449           genSetDPTR (0);
8450           _flushLazyDPS ();
8451
8452           emitcode ("clr", "a");
8453           emitcode ("movc", "a,@a+dptr");
8454           if (size)
8455             emitcode ("inc", "dptr");
8456           aopPut (AOP (result), "a", offset++);
8457         }
8458       _endLazyDPSEvaluation ();
8459     }
8460
8461   freeAsmop (result, NULL, ic, TRUE);
8462 }
8463
8464 /*-----------------------------------------------------------------*/
8465 /* genGenPointerGet - gget value from generic pointer space        */
8466 /*-----------------------------------------------------------------*/
8467 static void
8468 genGenPointerGet (operand * left,
8469                   operand * result, iCode * ic)
8470 {
8471   int size, offset;
8472   sym_link *retype = getSpec (operandType (result));
8473   sym_link *letype = getSpec (operandType (left));
8474
8475   D (emitcode (";", "genGenPointerGet "); );
8476
8477   aopOp (left, ic, FALSE, TRUE);
8478
8479   /* if the operand is already in dptr
8480      then we do nothing else we move the value to dptr */
8481   if (AOP_TYPE (left) != AOP_STR)
8482     {
8483       /* if this is remateriazable */
8484       if (AOP_TYPE (left) == AOP_IMMD)
8485         {
8486           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8487           emitcode ("mov", "b,#%d", pointerCode (retype));
8488         }
8489       else
8490         {                       /* we need to get it byte by byte */
8491           _startLazyDPSEvaluation ();
8492           if (AOP(left)->type==AOP_DPTR2) {
8493             char *l;
8494             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8495             genSetDPTR(0);
8496             _flushLazyDPS();
8497             emitcode ("mov", "dpl,%s", l);
8498             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8499             genSetDPTR(0);
8500             _flushLazyDPS();
8501             emitcode ("mov", "dph,%s", l);
8502             if (options.model == MODEL_FLAT24) {
8503               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8504               genSetDPTR(0);
8505               _flushLazyDPS();
8506               emitcode ("mov", "dpx,%s", l);
8507               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8508             } else {
8509               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8510             }
8511           } else {
8512             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8513             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8514             if (options.model == MODEL_FLAT24) {
8515               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8516               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8517             } else {
8518               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8519             }
8520           }
8521           _endLazyDPSEvaluation ();
8522         }
8523     }
8524   /* so dptr know contains the address */
8525   freeAsmop (left, NULL, ic, TRUE);
8526   aopOp (result, ic, FALSE, TRUE);
8527
8528   /* if bit then unpack */
8529   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8530     genUnpackBits (result, "dptr", GPOINTER);
8531   else
8532     {
8533       size = AOP_SIZE (result);
8534       offset = 0;
8535
8536       while (size--)
8537         {
8538           emitcode ("lcall", "__gptrget");
8539           aopPut (AOP (result), "a", offset++);
8540           if (size)
8541             emitcode ("inc", "dptr");
8542         }
8543     }
8544
8545   freeAsmop (result, NULL, ic, TRUE);
8546 }
8547
8548 /*-----------------------------------------------------------------*/
8549 /* genPointerGet - generate code for pointer get                   */
8550 /*-----------------------------------------------------------------*/
8551 static void
8552 genPointerGet (iCode * ic)
8553 {
8554   operand *left, *result;
8555   sym_link *type, *etype;
8556   int p_type;
8557
8558   D (emitcode (";", "genPointerGet ");
8559     );
8560
8561   left = IC_LEFT (ic);
8562   result = IC_RESULT (ic);
8563
8564   /* depending on the type of pointer we need to
8565      move it to the correct pointer register */
8566   type = operandType (left);
8567   etype = getSpec (type);
8568   /* if left is of type of pointer then it is simple */
8569   if (IS_PTR (type) && !IS_FUNC (type->next))
8570     p_type = DCL_TYPE (type);
8571   else
8572     {
8573       /* we have to go by the storage class */
8574       p_type = PTR_TYPE (SPEC_OCLS (etype));
8575     }
8576
8577   /* now that we have the pointer type we assign
8578      the pointer values */
8579   switch (p_type)
8580     {
8581
8582     case POINTER:
8583     case IPOINTER:
8584       genNearPointerGet (left, result, ic);
8585       break;
8586
8587     case PPOINTER:
8588       genPagedPointerGet (left, result, ic);
8589       break;
8590
8591     case FPOINTER:
8592       genFarPointerGet (left, result, ic);
8593       break;
8594
8595     case CPOINTER:
8596       emitcodePointerGet (left, result, ic);
8597       break;
8598
8599     case GPOINTER:
8600       genGenPointerGet (left, result, ic);
8601       break;
8602     }
8603
8604 }
8605
8606 /*-----------------------------------------------------------------*/
8607 /* genPackBits - generates code for packed bit storage             */
8608 /*-----------------------------------------------------------------*/
8609 static void
8610 genPackBits (sym_link * etype,
8611              operand * right,
8612              char *rname, int p_type)
8613 {
8614   int shCount = 0;
8615   int offset = 0;
8616   int rLen = 0;
8617   int blen, bstr;
8618   char *l;
8619
8620   blen = SPEC_BLEN (etype);
8621   bstr = SPEC_BSTR (etype);
8622
8623   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8624   MOVA (l);
8625
8626   /* if the bit lenth is less than or    */
8627   /* it exactly fits a byte then         */
8628   if (SPEC_BLEN (etype) <= 8)
8629     {
8630       shCount = SPEC_BSTR (etype);
8631
8632       /* shift left acc */
8633       AccLsh (shCount);
8634
8635       if (SPEC_BLEN (etype) < 8)
8636         {                       /* if smaller than a byte */
8637
8638
8639           switch (p_type)
8640             {
8641             case POINTER:
8642               emitcode ("mov", "b,a");
8643               emitcode ("mov", "a,@%s", rname);
8644               break;
8645
8646             case FPOINTER:
8647               emitcode ("mov", "b,a");
8648               emitcode ("movx", "a,@dptr");
8649               break;
8650
8651             case GPOINTER:
8652               emitcode ("push", "b");
8653               emitcode ("push", "acc");
8654               emitcode ("lcall", "__gptrget");
8655               emitcode ("pop", "b");
8656               break;
8657             }
8658
8659           emitcode ("anl", "a,#0x%02x", (unsigned char)
8660                     ((unsigned char) (0xFF << (blen + bstr)) |
8661                      (unsigned char) (0xFF >> (8 - bstr))));
8662           emitcode ("orl", "a,b");
8663           if (p_type == GPOINTER)
8664             emitcode ("pop", "b");
8665         }
8666     }
8667
8668   switch (p_type)
8669     {
8670     case POINTER:
8671       emitcode ("mov", "@%s,a", rname);
8672       break;
8673
8674     case FPOINTER:
8675       emitcode ("movx", "@dptr,a");
8676       break;
8677
8678     case GPOINTER:
8679       emitcode ("lcall", "__gptrput");
8680       break;
8681     }
8682
8683   /* if we r done */
8684   if (SPEC_BLEN (etype) <= 8)
8685     return;
8686
8687   emitcode ("inc", "%s", rname);
8688   rLen = SPEC_BLEN (etype);
8689
8690   /* now generate for lengths greater than one byte */
8691   while (1)
8692     {
8693
8694       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8695
8696       rLen -= 8;
8697       if (rLen < 8)
8698         break;
8699
8700       switch (p_type)
8701         {
8702         case POINTER:
8703           if (*l == '@')
8704             {
8705               MOVA (l);
8706               emitcode ("mov", "@%s,a", rname);
8707             }
8708           else
8709             emitcode ("mov", "@%s,%s", rname, l);
8710           break;
8711
8712         case FPOINTER:
8713           MOVA (l);
8714           emitcode ("movx", "@dptr,a");
8715           break;
8716
8717         case GPOINTER:
8718           MOVA (l);
8719           emitcode ("lcall", "__gptrput");
8720           break;
8721         }
8722       emitcode ("inc", "%s", rname);
8723     }
8724
8725   MOVA (l);
8726
8727   /* last last was not complete */
8728   if (rLen)
8729     {
8730       /* save the byte & read byte */
8731       switch (p_type)
8732         {
8733         case POINTER:
8734           emitcode ("mov", "b,a");
8735           emitcode ("mov", "a,@%s", rname);
8736           break;
8737
8738         case FPOINTER:
8739           emitcode ("mov", "b,a");
8740           emitcode ("movx", "a,@dptr");
8741           break;
8742
8743         case GPOINTER:
8744           emitcode ("push", "b");
8745           emitcode ("push", "acc");
8746           emitcode ("lcall", "__gptrget");
8747           emitcode ("pop", "b");
8748           break;
8749         }
8750
8751       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8752       emitcode ("orl", "a,b");
8753     }
8754
8755   if (p_type == GPOINTER)
8756     emitcode ("pop", "b");
8757
8758   switch (p_type)
8759     {
8760
8761     case POINTER:
8762       emitcode ("mov", "@%s,a", rname);
8763       break;
8764
8765     case FPOINTER:
8766       emitcode ("movx", "@dptr,a");
8767       break;
8768
8769     case GPOINTER:
8770       emitcode ("lcall", "__gptrput");
8771       break;
8772     }
8773 }
8774 /*-----------------------------------------------------------------*/
8775 /* genDataPointerSet - remat pointer to data space                 */
8776 /*-----------------------------------------------------------------*/
8777 static void
8778 genDataPointerSet (operand * right,
8779                    operand * result,
8780                    iCode * ic)
8781 {
8782   int size, offset = 0;
8783   char *l, buffer[256];
8784
8785   aopOp (right, ic, FALSE, FALSE);
8786
8787   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8788   size = AOP_SIZE (right);
8789   while (size--)
8790     {
8791       if (offset)
8792         sprintf (buffer, "(%s + %d)", l + 1, offset);
8793       else
8794         sprintf (buffer, "%s", l + 1);
8795       emitcode ("mov", "%s,%s", buffer,
8796                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8797     }
8798
8799   freeAsmop (right, NULL, ic, TRUE);
8800   freeAsmop (result, NULL, ic, TRUE);
8801 }
8802
8803 /*-----------------------------------------------------------------*/
8804 /* genNearPointerSet - emitcode for near pointer put                */
8805 /*-----------------------------------------------------------------*/
8806 static void
8807 genNearPointerSet (operand * right,
8808                    operand * result,
8809                    iCode * ic)
8810 {
8811   asmop *aop = NULL;
8812   regs *preg = NULL;
8813   char *rname, *l;
8814   sym_link *retype, *letype;
8815   sym_link *ptype = operandType (result);
8816
8817   retype = getSpec (operandType (right));
8818   letype = getSpec (ptype);
8819
8820   aopOp (result, ic, FALSE, FALSE);
8821
8822   /* if the result is rematerializable &
8823      in data space & not a bit variable */
8824   if (AOP_TYPE (result) == AOP_IMMD &&
8825       DCL_TYPE (ptype) == POINTER &&
8826       !IS_BITVAR (retype) &&
8827       !IS_BITVAR (letype))
8828     {
8829       genDataPointerSet (right, result, ic);
8830       return;
8831     }
8832
8833   /* if the value is already in a pointer register
8834      then don't need anything more */
8835   if (!AOP_INPREG (AOP (result)))
8836     {
8837       /* otherwise get a free pointer register */
8838       aop = newAsmop (0);
8839       preg = getFreePtr (ic, &aop, FALSE);
8840       emitcode ("mov", "%s,%s",
8841                 preg->name,
8842                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8843       rname = preg->name;
8844     }
8845   else
8846     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8847
8848   freeAsmop (result, NULL, ic, TRUE);
8849   aopOp (right, ic, FALSE, FALSE);
8850
8851   /* if bitfield then unpack the bits */
8852   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8853     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8854   else
8855     {
8856       /* we have can just get the values */
8857       int size = AOP_SIZE (right);
8858       int offset = 0;
8859
8860       while (size--)
8861         {
8862           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8863           if (*l == '@')
8864             {
8865               MOVA (l);
8866               emitcode ("mov", "@%s,a", rname);
8867             }
8868           else
8869             emitcode ("mov", "@%s,%s", rname, l);
8870           if (size)
8871             emitcode ("inc", "%s", rname);
8872           offset++;
8873         }
8874     }
8875
8876   /* now some housekeeping stuff */
8877   if (aop)
8878     {
8879       /* we had to allocate for this iCode */
8880       freeAsmop (NULL, aop, ic, TRUE);
8881     }
8882   else
8883     {
8884       /* we did not allocate which means left
8885          already in a pointer register, then
8886          if size > 0 && this could be used again
8887          we have to point it back to where it
8888          belongs */
8889       if (AOP_SIZE (right) > 1 &&
8890           !OP_SYMBOL (result)->remat &&
8891           (OP_SYMBOL (result)->liveTo > ic->seq ||
8892            ic->depth))
8893         {
8894           int size = AOP_SIZE (right) - 1;
8895           while (size--)
8896             emitcode ("dec", "%s", rname);
8897         }
8898     }
8899
8900   /* done */
8901   freeAsmop (right, NULL, ic, TRUE);
8902
8903
8904 }
8905
8906 /*-----------------------------------------------------------------*/
8907 /* genPagedPointerSet - emitcode for Paged pointer put             */
8908 /*-----------------------------------------------------------------*/
8909 static void
8910 genPagedPointerSet (operand * right,
8911                     operand * result,
8912                     iCode * ic)
8913 {
8914   asmop *aop = NULL;
8915   regs *preg = NULL;
8916   char *rname, *l;
8917   sym_link *retype, *letype;
8918
8919   retype = getSpec (operandType (right));
8920   letype = getSpec (operandType (result));
8921
8922   aopOp (result, ic, FALSE, FALSE);
8923
8924   /* if the value is already in a pointer register
8925      then don't need anything more */
8926   if (!AOP_INPREG (AOP (result)))
8927     {
8928       /* otherwise get a free pointer register */
8929       aop = newAsmop (0);
8930       preg = getFreePtr (ic, &aop, FALSE);
8931       emitcode ("mov", "%s,%s",
8932                 preg->name,
8933                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8934       rname = preg->name;
8935     }
8936   else
8937     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8938
8939   freeAsmop (result, NULL, ic, TRUE);
8940   aopOp (right, ic, FALSE, FALSE);
8941
8942   /* if bitfield then unpack the bits */
8943   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8944     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8945   else
8946     {
8947       /* we have can just get the values */
8948       int size = AOP_SIZE (right);
8949       int offset = 0;
8950
8951       while (size--)
8952         {
8953           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8954
8955           MOVA (l);
8956           emitcode ("movx", "@%s,a", rname);
8957
8958           if (size)
8959             emitcode ("inc", "%s", rname);
8960
8961           offset++;
8962         }
8963     }
8964
8965   /* now some housekeeping stuff */
8966   if (aop)
8967     {
8968       /* we had to allocate for this iCode */
8969       freeAsmop (NULL, aop, ic, TRUE);
8970     }
8971   else
8972     {
8973       /* we did not allocate which means left
8974          already in a pointer register, then
8975          if size > 0 && this could be used again
8976          we have to point it back to where it
8977          belongs */
8978       if (AOP_SIZE (right) > 1 &&
8979           !OP_SYMBOL (result)->remat &&
8980           (OP_SYMBOL (result)->liveTo > ic->seq ||
8981            ic->depth))
8982         {
8983           int size = AOP_SIZE (right) - 1;
8984           while (size--)
8985             emitcode ("dec", "%s", rname);
8986         }
8987     }
8988
8989   /* done */
8990   freeAsmop (right, NULL, ic, TRUE);
8991
8992
8993 }
8994
8995 /*-----------------------------------------------------------------*/
8996 /* genFarPointerSet - set value from far space                     */
8997 /*-----------------------------------------------------------------*/
8998 static void
8999 genFarPointerSet (operand * right,
9000                   operand * result, iCode * ic)
9001 {
9002   int size, offset;
9003   sym_link *retype = getSpec (operandType (right));
9004   sym_link *letype = getSpec (operandType (result));
9005
9006   aopOp (result, ic, FALSE, FALSE);
9007
9008   /* if the operand is already in dptr
9009      then we do nothing else we move the value to dptr */
9010   if (AOP_TYPE (result) != AOP_STR)
9011     {
9012       /* if this is remateriazable */
9013       if (AOP_TYPE (result) == AOP_IMMD)
9014         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9015       else
9016         {
9017           /* we need to get it byte by byte */
9018           _startLazyDPSEvaluation ();
9019           if (AOP_TYPE (result) != AOP_DPTR)
9020             {
9021               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9022               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9023               if (options.model == MODEL_FLAT24)
9024                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9025             }
9026           else
9027             {
9028               /* We need to generate a load to DPTR indirect through DPTR. */
9029               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9030                 );
9031               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9032               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9033               if (options.model == MODEL_FLAT24)
9034                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9035               emitcode ("pop", "dph");
9036               emitcode ("pop", "dpl");
9037             }
9038           _endLazyDPSEvaluation ();
9039         }
9040     }
9041   /* so dptr know contains the address */
9042   freeAsmop (result, NULL, ic, TRUE);
9043   aopOp (right, ic, FALSE, TRUE);
9044
9045   /* if bit then unpack */
9046   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9047     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9048   else
9049     {
9050       size = AOP_SIZE (right);
9051       offset = 0;
9052
9053       _startLazyDPSEvaluation ();
9054       while (size--)
9055         {
9056           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9057           MOVA (l);
9058
9059           genSetDPTR (0);
9060           _flushLazyDPS ();
9061
9062           emitcode ("movx", "@dptr,a");
9063           if (size)
9064             emitcode ("inc", "dptr");
9065         }
9066       _endLazyDPSEvaluation ();
9067     }
9068
9069   freeAsmop (right, NULL, ic, TRUE);
9070 }
9071
9072 /*-----------------------------------------------------------------*/
9073 /* genGenPointerSet - set value from generic pointer space         */
9074 /*-----------------------------------------------------------------*/
9075 static void
9076 genGenPointerSet (operand * right,
9077                   operand * result, iCode * ic)
9078 {
9079   int size, offset;
9080   sym_link *retype = getSpec (operandType (right));
9081   sym_link *letype = getSpec (operandType (result));
9082
9083   aopOp (result, ic, FALSE, TRUE);
9084
9085   /* if the operand is already in dptr
9086      then we do nothing else we move the value to dptr */
9087   if (AOP_TYPE (result) != AOP_STR)
9088     {
9089       _startLazyDPSEvaluation ();
9090       /* if this is remateriazable */
9091       if (AOP_TYPE (result) == AOP_IMMD)
9092         {
9093           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9094           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9095         }
9096       else
9097         {                       /* we need to get it byte by byte */
9098           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9099           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9100           if (options.model == MODEL_FLAT24) {
9101             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9102             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9103           } else {
9104             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9105           }
9106         }
9107       _endLazyDPSEvaluation ();
9108     }
9109   /* so dptr know contains the address */
9110   freeAsmop (result, NULL, ic, TRUE);
9111   aopOp (right, ic, FALSE, TRUE);
9112
9113   /* if bit then unpack */
9114   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9115     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9116   else
9117     {
9118       size = AOP_SIZE (right);
9119       offset = 0;
9120
9121       _startLazyDPSEvaluation ();
9122       while (size--)
9123         {
9124           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9125           MOVA (l);
9126
9127           genSetDPTR (0);
9128           _flushLazyDPS ();
9129
9130           emitcode ("lcall", "__gptrput");
9131           if (size)
9132             emitcode ("inc", "dptr");
9133         }
9134       _endLazyDPSEvaluation ();
9135     }
9136
9137   freeAsmop (right, NULL, ic, TRUE);
9138 }
9139
9140 /*-----------------------------------------------------------------*/
9141 /* genPointerSet - stores the value into a pointer location        */
9142 /*-----------------------------------------------------------------*/
9143 static void
9144 genPointerSet (iCode * ic)
9145 {
9146   operand *right, *result;
9147   sym_link *type, *etype;
9148   int p_type;
9149
9150   D (emitcode (";", "genPointerSet ");
9151     );
9152
9153   right = IC_RIGHT (ic);
9154   result = IC_RESULT (ic);
9155
9156   /* depending on the type of pointer we need to
9157      move it to the correct pointer register */
9158   type = operandType (result);
9159   etype = getSpec (type);
9160   /* if left is of type of pointer then it is simple */
9161   if (IS_PTR (type) && !IS_FUNC (type->next))
9162     {
9163       p_type = DCL_TYPE (type);
9164     }
9165   else
9166     {
9167       /* we have to go by the storage class */
9168       p_type = PTR_TYPE (SPEC_OCLS (etype));
9169     }
9170
9171   /* now that we have the pointer type we assign
9172      the pointer values */
9173   switch (p_type)
9174     {
9175
9176     case POINTER:
9177     case IPOINTER:
9178       genNearPointerSet (right, result, ic);
9179       break;
9180
9181     case PPOINTER:
9182       genPagedPointerSet (right, result, ic);
9183       break;
9184
9185     case FPOINTER:
9186       genFarPointerSet (right, result, ic);
9187       break;
9188
9189     case GPOINTER:
9190       genGenPointerSet (right, result, ic);
9191       break;
9192     }
9193
9194 }
9195
9196 /*-----------------------------------------------------------------*/
9197 /* genIfx - generate code for Ifx statement                        */
9198 /*-----------------------------------------------------------------*/
9199 static void
9200 genIfx (iCode * ic, iCode * popIc)
9201 {
9202   operand *cond = IC_COND (ic);
9203   int isbit = 0;
9204
9205   D (emitcode (";", "genIfx "););
9206
9207   aopOp (cond, ic, FALSE, FALSE);
9208
9209   /* get the value into acc */
9210   if (AOP_TYPE (cond) != AOP_CRY)
9211     toBoolean (cond);
9212   else
9213     isbit = 1;
9214   /* the result is now in the accumulator */
9215   freeAsmop (cond, NULL, ic, TRUE);
9216
9217   /* if there was something to be popped then do it */
9218   if (popIc)
9219     genIpop (popIc);
9220
9221   /* if the condition is  a bit variable */
9222   if (isbit && IS_ITEMP (cond) &&
9223       SPIL_LOC (cond))
9224     genIfxJump (ic, SPIL_LOC (cond)->rname);
9225   else if (isbit && !IS_ITEMP (cond))
9226     genIfxJump (ic, OP_SYMBOL (cond)->rname);
9227   else
9228     genIfxJump (ic, "a");
9229
9230   ic->generated = 1;
9231 }
9232
9233 /*-----------------------------------------------------------------*/
9234 /* genAddrOf - generates code for address of                       */
9235 /*-----------------------------------------------------------------*/
9236 static void
9237 genAddrOf (iCode * ic)
9238 {
9239   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9240   int size, offset;
9241
9242   D (emitcode (";", "genAddrOf ");
9243     );
9244
9245   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9246
9247   /* if the operand is on the stack then we
9248      need to get the stack offset of this
9249      variable */
9250   if (sym->onStack)
9251     {
9252       /* if it has an offset then we need to compute
9253          it */
9254       if (sym->stack)
9255         {
9256           emitcode ("mov", "a,_bp");
9257           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9258           aopPut (AOP (IC_RESULT (ic)), "a", 0);
9259         }
9260       else
9261         {
9262           /* we can just move _bp */
9263           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9264         }
9265       /* fill the result with zero */
9266       size = AOP_SIZE (IC_RESULT (ic)) - 1;
9267
9268
9269       if (options.stack10bit && size < (FPTRSIZE - 1))
9270         {
9271           fprintf (stderr,
9272                    "*** warning: pointer to stack var truncated.\n");
9273         }
9274
9275       offset = 1;
9276       while (size--)
9277         {
9278           /* Yuck! */
9279           if (options.stack10bit && offset == 2)
9280             {
9281               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9282             }
9283           else
9284             {
9285               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9286             }
9287         }
9288
9289       goto release;
9290     }
9291
9292   /* object not on stack then we need the name */
9293   size = AOP_SIZE (IC_RESULT (ic));
9294   offset = 0;
9295
9296   while (size--)
9297     {
9298       char s[SDCC_NAME_MAX];
9299       if (offset)
9300         sprintf (s, "#(%s >> %d)",
9301                  sym->rname,
9302                  offset * 8);
9303       else
9304         sprintf (s, "#%s", sym->rname);
9305       aopPut (AOP (IC_RESULT (ic)), s, offset++);
9306     }
9307
9308 release:
9309   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9310
9311 }
9312
9313 /*-----------------------------------------------------------------*/
9314 /* genArrayInit - generates code for address of                       */
9315 /*-----------------------------------------------------------------*/
9316 static void
9317 genArrayInit (iCode * ic)
9318 {
9319     literalList *iLoop;
9320     int         ix, count;
9321     int         elementSize = 0, eIndex;
9322     unsigned    val, lastVal;
9323     sym_link    *type;
9324     operand     *left=IC_LEFT(ic);
9325     
9326     D (emitcode (";", "genArrayInit "););
9327
9328     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9329     
9330     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9331     {
9332         // Load immediate value into DPTR.
9333         emitcode("mov", "dptr, %s",
9334              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9335     }
9336     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9337     {
9338 #if 0
9339       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9340               "Unexpected operand to genArrayInit.\n");
9341       exit(1);
9342 #else
9343       // a regression because of SDCCcse.c:1.52
9344       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9345       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9346       if (options.model == MODEL_FLAT24)
9347         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9348 #endif
9349     }
9350     
9351     type = operandType(IC_LEFT(ic));
9352     
9353     if (type && type->next)
9354     {
9355         elementSize = getSize(type->next);
9356     }
9357     else
9358     {
9359         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9360                                 "can't determine element size in genArrayInit.\n");
9361         exit(1);
9362     }
9363     
9364     iLoop = IC_ARRAYILIST(ic);
9365     lastVal = 0xffff;
9366     
9367     while (iLoop)
9368     {
9369         bool firstpass = TRUE;
9370         
9371         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
9372                  iLoop->count, (int)iLoop->literalValue, elementSize);
9373         
9374         ix = iLoop->count;
9375         
9376         while (ix)
9377         {
9378             symbol *tlbl = NULL;
9379             
9380             count = ix > 256 ? 256 : ix;
9381             
9382             if (count > 1)
9383             {
9384                 tlbl = newiTempLabel (NULL);
9385                 if (firstpass || (count & 0xff))
9386                 {
9387                     emitcode("mov", "b, #0x%x", count & 0xff);
9388                 }
9389                 
9390                 emitcode ("", "%05d$:", tlbl->key + 100);
9391             }
9392             
9393             firstpass = FALSE;
9394                 
9395             for (eIndex = 0; eIndex < elementSize; eIndex++)
9396             {
9397                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9398                 if (val != lastVal)
9399                 {
9400                     emitcode("mov", "a, #0x%x", val);
9401                     lastVal = val;
9402                 }
9403                 
9404                 emitcode("movx", "@dptr, a");
9405                 emitcode("inc", "dptr");
9406             }
9407             
9408             if (count > 1)
9409             {
9410                 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9411             }
9412             
9413             ix -= count;
9414         }
9415         
9416         iLoop = iLoop->next;
9417     }
9418     
9419     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9420 }
9421
9422 /*-----------------------------------------------------------------*/
9423 /* genFarFarAssign - assignment when both are in far space         */
9424 /*-----------------------------------------------------------------*/
9425 static void
9426 genFarFarAssign (operand * result, operand * right, iCode * ic)
9427 {
9428   int size = AOP_SIZE (right);
9429   int offset = 0;
9430   symbol *rSym = NULL;
9431
9432   if (size == 1)
9433   {
9434       /* quick & easy case. */
9435       D(emitcode(";","genFarFarAssign (1 byte case)"););      
9436       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9437       freeAsmop (right, NULL, ic, FALSE);
9438       /* now assign DPTR to result */
9439       _G.accInUse++;
9440       aopOp(result, ic, FALSE, FALSE);
9441       _G.accInUse--;
9442       aopPut(AOP(result), "a", 0);
9443       freeAsmop(result, NULL, ic, FALSE);
9444       return;
9445   }
9446   
9447   /* See if we've got an underlying symbol to abuse. */
9448   if (IS_SYMOP(result) && OP_SYMBOL(result))
9449   {
9450       if (IS_TRUE_SYMOP(result))
9451       {
9452           rSym = OP_SYMBOL(result);
9453       }
9454       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9455       {
9456           rSym = OP_SYMBOL(result)->usl.spillLoc;
9457       }
9458   }
9459              
9460   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9461   {
9462       /* We can use the '390 auto-toggle feature to good effect here. */
9463       
9464       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9465       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
9466       emitcode ("mov", "dptr,#%s", rSym->rname); 
9467       /* DP2 = result, DP1 = right, DP1 is current. */
9468       while (size)
9469       {
9470           emitcode("movx", "a,@dptr");
9471           emitcode("movx", "@dptr,a");
9472           if (--size)
9473           {
9474                emitcode("inc", "dptr");
9475                emitcode("inc", "dptr");
9476           }
9477       }
9478       emitcode("mov", "dps, #0");
9479       freeAsmop (right, NULL, ic, FALSE);
9480 #if 0
9481 some alternative code for processors without auto-toggle
9482 no time to test now, so later well put in...kpb
9483         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9484         emitcode("mov", "dps, #0x01");  /* Select DPTR2. */
9485         emitcode ("mov", "dptr,#%s", rSym->rname); 
9486         /* DP2 = result, DP1 = right, DP1 is current. */
9487         while (size)
9488         {
9489           --size;
9490           emitcode("movx", "a,@dptr");
9491           if (size)
9492             emitcode("inc", "dptr");
9493           emitcode("inc", "dps");
9494           emitcode("movx", "@dptr,a");
9495           if (size)
9496             emitcode("inc", "dptr");
9497           emitcode("inc", "dps");
9498         }
9499         emitcode("mov", "dps, #0");
9500         freeAsmop (right, NULL, ic, FALSE);
9501 #endif
9502   }
9503   else
9504   {
9505       D (emitcode (";", "genFarFarAssign"););
9506       aopOp (result, ic, TRUE, TRUE);
9507
9508       _startLazyDPSEvaluation ();
9509       
9510       while (size--)
9511         {
9512           aopPut (AOP (result),
9513                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9514           offset++;
9515         }
9516       _endLazyDPSEvaluation ();
9517       freeAsmop (result, NULL, ic, FALSE);
9518       freeAsmop (right, NULL, ic, FALSE);
9519   }
9520 }
9521
9522 /*-----------------------------------------------------------------*/
9523 /* genAssign - generate code for assignment                        */
9524 /*-----------------------------------------------------------------*/
9525 static void
9526 genAssign (iCode * ic)
9527 {
9528   operand *result, *right;
9529   int size, offset;
9530   unsigned long lit = 0L;
9531
9532   D (emitcode (";", "genAssign ");
9533     );
9534
9535   result = IC_RESULT (ic);
9536   right = IC_RIGHT (ic);
9537
9538   /* if they are the same */
9539   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9540     return;
9541
9542   aopOp (right, ic, FALSE, FALSE);
9543
9544   emitcode (";", "genAssign: resultIsFar = %s",
9545             isOperandInFarSpace (result) ?
9546             "TRUE" : "FALSE");
9547
9548   /* special case both in far space */
9549   if ((AOP_TYPE (right) == AOP_DPTR ||
9550        AOP_TYPE (right) == AOP_DPTR2) &&
9551   /* IS_TRUE_SYMOP(result)       && */
9552       isOperandInFarSpace (result))
9553     {
9554       genFarFarAssign (result, right, ic);
9555       return;
9556     }
9557
9558   aopOp (result, ic, TRUE, FALSE);
9559
9560   /* if they are the same registers */
9561   if (sameRegs (AOP (right), AOP (result)))
9562     goto release;
9563
9564   /* if the result is a bit */
9565   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9566     {
9567       /* if the right size is a literal then
9568          we know what the value is */
9569       if (AOP_TYPE (right) == AOP_LIT)
9570         {
9571           if (((int) operandLitValue (right)))
9572             aopPut (AOP (result), one, 0);
9573           else
9574             aopPut (AOP (result), zero, 0);
9575           goto release;
9576         }
9577
9578       /* the right is also a bit variable */
9579       if (AOP_TYPE (right) == AOP_CRY)
9580         {
9581           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9582           aopPut (AOP (result), "c", 0);
9583           goto release;
9584         }
9585
9586       /* we need to or */
9587       toBoolean (right);
9588       aopPut (AOP (result), "a", 0);
9589       goto release;
9590     }
9591
9592   /* bit variables done */
9593   /* general case */
9594   size = AOP_SIZE (result);
9595   offset = 0;
9596   if (AOP_TYPE (right) == AOP_LIT)
9597     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9598
9599   if ((size > 1) &&
9600       (AOP_TYPE (result) != AOP_REG) &&
9601       (AOP_TYPE (right) == AOP_LIT) &&
9602       !IS_FLOAT (operandType (right)))
9603     {
9604       _startLazyDPSEvaluation ();
9605       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9606         {
9607           aopPut (AOP (result),
9608                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9609                   offset);
9610           offset++;
9611           size--;
9612         }
9613       /* And now fill the rest with zeros. */
9614       if (size)
9615         {
9616           emitcode ("clr", "a");
9617         }
9618       while (size--)
9619         {
9620           aopPut (AOP (result), "a", offset++);
9621         }
9622       _endLazyDPSEvaluation ();
9623     }
9624   else
9625     {
9626       _startLazyDPSEvaluation ();
9627       while (size--)
9628         {
9629           aopPut (AOP (result),
9630                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9631                   offset);
9632           offset++;
9633         }
9634       _endLazyDPSEvaluation ();
9635     }
9636
9637 release:
9638   freeAsmop (right, NULL, ic, FALSE);
9639   freeAsmop (result, NULL, ic, TRUE);
9640 }
9641
9642 /*-----------------------------------------------------------------*/
9643 /* genJumpTab - generates code for jump table                      */
9644 /*-----------------------------------------------------------------*/
9645 static void
9646 genJumpTab (iCode * ic)
9647 {
9648   symbol *jtab;
9649   char *l;
9650
9651   D (emitcode (";", "genJumpTab ");
9652     );
9653
9654   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9655   /* get the condition into accumulator */
9656   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9657   MOVA (l);
9658   /* multiply by four! */
9659   emitcode ("add", "a,acc");
9660   emitcode ("add", "a,acc");
9661   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9662
9663   jtab = newiTempLabel (NULL);
9664   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9665   emitcode ("jmp", "@a+dptr");
9666   emitcode ("", "%05d$:", jtab->key + 100);
9667   /* now generate the jump labels */
9668   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9669        jtab = setNextItem (IC_JTLABELS (ic)))
9670     emitcode ("ljmp", "%05d$", jtab->key + 100);
9671
9672 }
9673
9674 /*-----------------------------------------------------------------*/
9675 /* genCast - gen code for casting                                  */
9676 /*-----------------------------------------------------------------*/
9677 static void
9678 genCast (iCode * ic)
9679 {
9680   operand *result = IC_RESULT (ic);
9681   sym_link *ctype = operandType (IC_LEFT (ic));
9682   sym_link *rtype = operandType (IC_RIGHT (ic));
9683   operand *right = IC_RIGHT (ic);
9684   int size, offset;
9685
9686   D (emitcode (";", "genCast ");
9687     );
9688
9689   /* if they are equivalent then do nothing */
9690   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9691     return;
9692
9693   aopOp (right, ic, FALSE, FALSE);
9694   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9695
9696   /* if the result is a bit */
9697   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9698   if (IS_BITVAR(OP_SYMBOL(result)->type))
9699     {
9700       /* if the right size is a literal then
9701          we know what the value is */
9702       if (AOP_TYPE (right) == AOP_LIT)
9703         {
9704           if (((int) operandLitValue (right)))
9705             aopPut (AOP (result), one, 0);
9706           else
9707             aopPut (AOP (result), zero, 0);
9708
9709           goto release;
9710         }
9711
9712       /* the right is also a bit variable */
9713       if (AOP_TYPE (right) == AOP_CRY)
9714         {
9715           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9716           aopPut (AOP (result), "c", 0);
9717           goto release;
9718         }
9719
9720       /* we need to or */
9721       toBoolean (right);
9722       aopPut (AOP (result), "a", 0);
9723       goto release;
9724     }
9725
9726   /* if they are the same size : or less */
9727   if (AOP_SIZE (result) <= AOP_SIZE (right))
9728     {
9729
9730       /* if they are in the same place */
9731       if (sameRegs (AOP (right), AOP (result)))
9732         goto release;
9733
9734       /* if they in different places then copy */
9735       size = AOP_SIZE (result);
9736       offset = 0;
9737       _startLazyDPSEvaluation ();
9738       while (size--)
9739         {
9740           aopPut (AOP (result),
9741                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9742                   offset);
9743           offset++;
9744         }
9745       _endLazyDPSEvaluation ();
9746       goto release;
9747     }
9748
9749
9750   /* if the result is of type pointer */
9751   if (IS_PTR (ctype))
9752     {
9753
9754       int p_type;
9755       sym_link *type = operandType (right);
9756
9757       /* pointer to generic pointer */
9758       if (IS_GENPTR (ctype))
9759         {
9760           char *l = zero;
9761
9762           if (IS_PTR (type))
9763             {
9764               p_type = DCL_TYPE (type);
9765             }
9766           else
9767             {
9768 #if OLD_CAST_BEHAVIOR
9769               /* KV: we are converting a non-pointer type to
9770                * a generic pointer. This (ifdef'd out) code
9771                * says that the resulting generic pointer
9772                * should have the same class as the storage
9773                * location of the non-pointer variable.
9774                *
9775                * For example, converting an int (which happens
9776                * to be stored in DATA space) to a pointer results
9777                * in a DATA generic pointer; if the original int
9778                * in XDATA space, so will be the resulting pointer.
9779                *
9780                * I don't like that behavior, and thus this change:
9781                * all such conversions will be forced to XDATA and
9782                * throw a warning. If you want some non-XDATA
9783                * type, or you want to suppress the warning, you
9784                * must go through an intermediate cast, like so:
9785                *
9786                * char _generic *gp = (char _xdata *)(intVar);
9787                */
9788               sym_link *etype = getSpec (type);
9789
9790               /* we have to go by the storage class */
9791               if (SPEC_OCLS (etype) != generic)
9792                 {
9793                   p_type = PTR_TYPE (SPEC_OCLS (etype));
9794                 }
9795               else
9796 #endif
9797                 {
9798                   /* Converting unknown class (i.e. register variable)
9799                    * to generic pointer. This is not good, but
9800                    * we'll make a guess (and throw a warning).
9801                    */
9802                   p_type = FPOINTER;
9803                   werror (W_INT_TO_GEN_PTR_CAST);
9804                 }
9805             }
9806
9807           /* the first two bytes are known */
9808           size = GPTRSIZE - 1;
9809           offset = 0;
9810           _startLazyDPSEvaluation ();
9811           while (size--)
9812             {
9813               aopPut (AOP (result),
9814                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9815                       offset);
9816               offset++;
9817             }
9818           _endLazyDPSEvaluation ();
9819
9820           /* the last byte depending on type */
9821           switch (p_type)
9822             {
9823             case IPOINTER:
9824             case POINTER:
9825               l = zero;
9826               break;
9827             case FPOINTER:
9828               l = one;
9829               break;
9830             case CPOINTER:
9831               l = "#0x02";
9832               break;
9833             case PPOINTER:
9834               l = "#0x03";
9835               break;
9836
9837             default:
9838               /* this should never happen */
9839               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9840                       "got unknown pointer type");
9841               exit (1);
9842             }
9843           aopPut (AOP (result), l, GPTRSIZE - 1);
9844           goto release;
9845         }
9846
9847       /* just copy the pointers */
9848       size = AOP_SIZE (result);
9849       offset = 0;
9850       _startLazyDPSEvaluation ();
9851       while (size--)
9852         {
9853           aopPut (AOP (result),
9854                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9855                   offset);
9856           offset++;
9857         }
9858       _endLazyDPSEvaluation ();
9859       goto release;
9860     }
9861
9862   /* so we now know that the size of destination is greater
9863      than the size of the source */
9864   /* we move to result for the size of source */
9865   size = AOP_SIZE (right);
9866   offset = 0;
9867   _startLazyDPSEvaluation ();
9868   while (size--)
9869     {
9870       aopPut (AOP (result),
9871               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9872               offset);
9873       offset++;
9874     }
9875   _endLazyDPSEvaluation ();
9876
9877   /* now depending on the sign of the source && destination */
9878   size = AOP_SIZE (result) - AOP_SIZE (right);
9879   /* if unsigned or not an integral type */
9880   /* also, if the source is a bit, we don't need to sign extend, because
9881    * it can't possibly have set the sign bit.
9882    */
9883   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9884     {
9885       while (size--)
9886         {
9887           aopPut (AOP (result), zero, offset++);
9888         }
9889     }
9890   else
9891     {
9892       /* we need to extend the sign :{ */
9893       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9894                         FALSE, FALSE, TRUE);
9895       MOVA (l);
9896       emitcode ("rlc", "a");
9897       emitcode ("subb", "a,acc");
9898       while (size--)
9899         aopPut (AOP (result), "a", offset++);
9900     }
9901
9902   /* we are done hurray !!!! */
9903
9904 release:
9905   freeAsmop (right, NULL, ic, TRUE);
9906   freeAsmop (result, NULL, ic, TRUE);
9907
9908 }
9909
9910 /*-----------------------------------------------------------------*/
9911 /* genDjnz - generate decrement & jump if not zero instrucion      */
9912 /*-----------------------------------------------------------------*/
9913 static int
9914 genDjnz (iCode * ic, iCode * ifx)
9915 {
9916   symbol *lbl, *lbl1;
9917   if (!ifx)
9918     return 0;
9919
9920   /* if the if condition has a false label
9921      then we cannot save */
9922   if (IC_FALSE (ifx))
9923     return 0;
9924
9925   /* if the minus is not of the form
9926      a = a - 1 */
9927   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9928       !IS_OP_LITERAL (IC_RIGHT (ic)))
9929     return 0;
9930
9931   if (operandLitValue (IC_RIGHT (ic)) != 1)
9932     return 0;
9933
9934   /* if the size of this greater than one then no
9935      saving */
9936   if (getSize (operandType (IC_RESULT (ic))) > 1)
9937     return 0;
9938
9939   /* otherwise we can save BIG */
9940   D(emitcode(";", "genDjnz"););
9941
9942   lbl = newiTempLabel (NULL);
9943   lbl1 = newiTempLabel (NULL);
9944
9945   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9946
9947   if (AOP_NEEDSACC(IC_RESULT(ic)))
9948   {
9949       /* If the result is accessed indirectly via
9950        * the accumulator, we must explicitly write
9951        * it back after the decrement.
9952        */
9953       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9954       
9955       if (strcmp(rByte, "a"))
9956       {
9957            /* Something is hopelessly wrong */
9958            fprintf(stderr, "*** warning: internal error at %s:%d\n",
9959                    __FILE__, __LINE__);
9960            /* We can just give up; the generated code will be inefficient,
9961             * but what the hey.
9962             */
9963            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9964            return 0;
9965       }
9966       emitcode ("dec", "%s", rByte);
9967       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9968       emitcode ("jnz", "%05d$", lbl->key + 100);
9969   }
9970   else if (IS_AOP_PREG (IC_RESULT (ic)))
9971     {
9972       emitcode ("dec", "%s",
9973                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9974       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9975       emitcode ("jnz", "%05d$", lbl->key + 100);
9976     }
9977   else
9978     {
9979       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
9980                 lbl->key + 100);
9981     }
9982   emitcode ("sjmp", "%05d$", lbl1->key + 100);
9983   emitcode ("", "%05d$:", lbl->key + 100);
9984   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9985   emitcode ("", "%05d$:", lbl1->key + 100);
9986
9987   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9988   ifx->generated = 1;
9989   return 1;
9990 }
9991
9992 /*-----------------------------------------------------------------*/
9993 /* genReceive - generate code for a receive iCode                  */
9994 /*-----------------------------------------------------------------*/
9995 static void
9996 genReceive (iCode * ic)
9997 {
9998
9999   D (emitcode (";", "genReceive ");
10000     );
10001
10002   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10003       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10004        IS_TRUE_SYMOP (IC_RESULT (ic))))
10005     {
10006       int size = getSize (operandType (IC_RESULT (ic)));
10007       int offset = fReturnSizeDS390 - size;
10008       while (size--)
10009         {
10010           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10011                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10012           offset++;
10013         }
10014       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10015       size = AOP_SIZE (IC_RESULT (ic));
10016       offset = 0;
10017       while (size--)
10018         {
10019           emitcode ("pop", "acc");
10020           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10021         }
10022
10023     }
10024   else
10025     {
10026       _G.accInUse++;
10027       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10028       _G.accInUse--;
10029       assignResultValue (IC_RESULT (ic));
10030     }
10031
10032   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10033 }
10034
10035 /*-----------------------------------------------------------------*/
10036 /* gen390Code - generate code for Dallas 390 based controllers     */
10037 /*-----------------------------------------------------------------*/
10038 void
10039 gen390Code (iCode * lic)
10040 {
10041   iCode *ic;
10042   int cln = 0;
10043
10044   lineHead = lineCurr = NULL;
10045
10046   if (options.model == MODEL_FLAT24) {
10047     fReturnSizeDS390 = 5;
10048     fReturn = fReturn24;
10049   } else {
10050     fReturnSizeDS390 = 4;
10051     fReturn = fReturn16;
10052     options.stack10bit=0;
10053   }
10054 #if 0
10055   //REMOVE ME!!!
10056   /* print the allocation information */
10057   if (allocInfo)
10058     printAllocInfo (currFunc, codeOutFile);
10059 #endif
10060   /* if debug information required */
10061   if (options.debug && currFunc)
10062     {
10063       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10064       _G.debugLine = 1;
10065       if (IS_STATIC (currFunc->etype))
10066         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10067       else
10068         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10069       _G.debugLine = 0;
10070     }
10071   /* stack pointer name */
10072   if (options.useXstack)
10073     spname = "_spx";
10074   else
10075     spname = "sp";
10076
10077
10078   for (ic = lic; ic; ic = ic->next)
10079     {
10080
10081       if (cln != ic->lineno)
10082         {
10083           if (options.debug)
10084             {
10085               _G.debugLine = 1;
10086               emitcode ("", "C$%s$%d$%d$%d ==.",
10087                         FileBaseName (ic->filename), ic->lineno,
10088                         ic->level, ic->block);
10089               _G.debugLine = 0;
10090             }
10091           emitcode (";", "%s %d", ic->filename, ic->lineno);
10092           cln = ic->lineno;
10093         }
10094       /* if the result is marked as
10095          spilt and rematerializable or code for
10096          this has already been generated then
10097          do nothing */
10098       if (resultRemat (ic) || ic->generated)
10099         continue;
10100
10101       /* depending on the operation */
10102       switch (ic->op)
10103         {
10104         case '!':
10105           genNot (ic);
10106           break;
10107
10108         case '~':
10109           genCpl (ic);
10110           break;
10111
10112         case UNARYMINUS:
10113           genUminus (ic);
10114           break;
10115
10116         case IPUSH:
10117           genIpush (ic);
10118           break;
10119
10120         case IPOP:
10121           /* IPOP happens only when trying to restore a
10122              spilt live range, if there is an ifx statement
10123              following this pop then the if statement might
10124              be using some of the registers being popped which
10125              would destory the contents of the register so
10126              we need to check for this condition and handle it */
10127           if (ic->next &&
10128               ic->next->op == IFX &&
10129               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10130             genIfx (ic->next, ic);
10131           else
10132             genIpop (ic);
10133           break;
10134
10135         case CALL:
10136           genCall (ic);
10137           break;
10138
10139         case PCALL:
10140           genPcall (ic);
10141           break;
10142
10143         case FUNCTION:
10144           genFunction (ic);
10145           break;
10146
10147         case ENDFUNCTION:
10148           genEndFunction (ic);
10149           break;
10150
10151         case RETURN:
10152           genRet (ic);
10153           break;
10154
10155         case LABEL:
10156           genLabel (ic);
10157           break;
10158
10159         case GOTO:
10160           genGoto (ic);
10161           break;
10162
10163         case '+':
10164           genPlus (ic);
10165           break;
10166
10167         case '-':
10168           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10169             genMinus (ic);
10170           break;
10171
10172         case '*':
10173           genMult (ic);
10174           break;
10175
10176         case '/':
10177           genDiv (ic);
10178           break;
10179
10180         case '%':
10181           genMod (ic);
10182           break;
10183
10184         case '>':
10185           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10186           break;
10187
10188         case '<':
10189           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10190           break;
10191
10192         case LE_OP:
10193         case GE_OP:
10194         case NE_OP:
10195
10196           /* note these two are xlated by algebraic equivalence
10197              during parsing SDCC.y */
10198           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10199                   "got '>=' or '<=' shouldn't have come here");
10200           break;
10201
10202         case EQ_OP:
10203           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10204           break;
10205
10206         case AND_OP:
10207           genAndOp (ic);
10208           break;
10209
10210         case OR_OP:
10211           genOrOp (ic);
10212           break;
10213
10214         case '^':
10215           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10216           break;
10217
10218         case '|':
10219           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10220           break;
10221
10222         case BITWISEAND:
10223           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10224           break;
10225
10226         case INLINEASM:
10227           genInline (ic);
10228           break;
10229
10230         case RRC:
10231           genRRC (ic);
10232           break;
10233
10234         case RLC:
10235           genRLC (ic);
10236           break;
10237
10238         case GETHBIT:
10239           genGetHbit (ic);
10240           break;
10241
10242         case LEFT_OP:
10243           genLeftShift (ic);
10244           break;
10245
10246         case RIGHT_OP:
10247           genRightShift (ic);
10248           break;
10249
10250         case GET_VALUE_AT_ADDRESS:
10251           genPointerGet (ic);
10252           break;
10253
10254         case '=':
10255           if (POINTER_SET (ic))
10256             genPointerSet (ic);
10257           else
10258             genAssign (ic);
10259           break;
10260
10261         case IFX:
10262           genIfx (ic, NULL);
10263           break;
10264
10265         case ADDRESS_OF:
10266           genAddrOf (ic);
10267           break;
10268
10269         case JUMPTABLE:
10270           genJumpTab (ic);
10271           break;
10272
10273         case CAST:
10274           genCast (ic);
10275           break;
10276
10277         case RECEIVE:
10278           genReceive (ic);
10279           break;
10280
10281         case SEND:
10282           addSet (&_G.sendSet, ic);
10283           break;
10284
10285         case ARRAYINIT:
10286             genArrayInit(ic);
10287             break;
10288             
10289         default:
10290           ic = ic;
10291         }
10292     }
10293
10294
10295   /* now we are ready to call the
10296      peep hole optimizer */
10297   if (!options.nopeep)
10298     peepHole (&lineHead);
10299
10300   /* now do the actual printing */
10301   printLine (lineHead, codeOutFile);
10302   return;
10303 }