fix some grossness in the logic operations (genAnd, genOr, genXor)
[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 #ifdef LOGIC_OPS_BROKEN      
5217     ||  AOP_NEEDSACC (left)
5218 #endif
5219     )
5220     {
5221       operand *tmp = right;
5222       right = left;
5223       left = tmp;
5224     }
5225
5226   /* if result = right then exchange them */
5227   if (sameRegs (AOP (result), AOP (right)))
5228     {
5229       operand *tmp = right;
5230       right = left;
5231       left = tmp;
5232     }
5233
5234   /* if right is bit then exchange them */
5235   if (AOP_TYPE (right) == AOP_CRY &&
5236       AOP_TYPE (left) != AOP_CRY)
5237     {
5238       operand *tmp = right;
5239       right = left;
5240       left = tmp;
5241     }
5242   if (AOP_TYPE (right) == AOP_LIT)
5243     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5244
5245   size = AOP_SIZE (result);
5246
5247   // if(bit & yy)
5248   // result = bit & yy;
5249   if (AOP_TYPE (left) == AOP_CRY)
5250     {
5251       // c = bit & literal;
5252       if (AOP_TYPE (right) == AOP_LIT)
5253         {
5254           if (lit & 1)
5255             {
5256               if (size && sameRegs (AOP (result), AOP (left)))
5257                 // no change
5258                 goto release;
5259               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5260             }
5261           else
5262             {
5263               // bit(result) = 0;
5264               if (size && (AOP_TYPE (result) == AOP_CRY))
5265                 {
5266                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5267                   goto release;
5268                 }
5269               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5270                 {
5271                   jumpIfTrue (ifx);
5272                   goto release;
5273                 }
5274               emitcode ("clr", "c");
5275             }
5276         }
5277       else
5278         {
5279           if (AOP_TYPE (right) == AOP_CRY)
5280             {
5281               // c = bit & bit;
5282               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5283               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5284             }
5285           else
5286             {
5287               // c = bit & val;
5288               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5289               // c = lsb
5290               emitcode ("rrc", "a");
5291               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5292             }
5293         }
5294       // bit = c
5295       // val = c
5296       if (size)
5297         outBitC (result);
5298       // if(bit & ...)
5299       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5300         genIfxJump (ifx, "c");
5301       goto release;
5302     }
5303
5304   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5305   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5306   if ((AOP_TYPE (right) == AOP_LIT) &&
5307       (AOP_TYPE (result) == AOP_CRY) &&
5308       (AOP_TYPE (left) != AOP_CRY))
5309     {
5310       int posbit = isLiteralBit (lit);
5311       /* left &  2^n */
5312       if (posbit)
5313         {
5314           posbit--;
5315           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5316           // bit = left & 2^n
5317           if (size)
5318             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5319           // if(left &  2^n)
5320           else
5321             {
5322               if (ifx)
5323                 {
5324                   sprintf (buffer, "acc.%d", posbit & 0x07);
5325                   genIfxJump (ifx, buffer);
5326                 }
5327               goto release;
5328             }
5329         }
5330       else
5331         {
5332           symbol *tlbl = newiTempLabel (NULL);
5333           int sizel = AOP_SIZE (left);
5334           if (size)
5335             emitcode ("setb", "c");
5336           while (sizel--)
5337             {
5338               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5339                 {
5340                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5341                   // byte ==  2^n ?
5342                   if ((posbit = isLiteralBit (bytelit)) != 0)
5343                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5344                   else
5345                     {
5346                       if (bytelit != 0x0FFL)
5347                         emitcode ("anl", "a,%s",
5348                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5349                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5350                     }
5351                 }
5352               offset++;
5353             }
5354           // bit = left & literal
5355           if (size)
5356             {
5357               emitcode ("clr", "c");
5358               emitcode ("", "%05d$:", tlbl->key + 100);
5359             }
5360           // if(left & literal)
5361           else
5362             {
5363               if (ifx)
5364                 jmpTrueOrFalse (ifx, tlbl);
5365               goto release;
5366             }
5367         }
5368       outBitC (result);
5369       goto release;
5370     }
5371
5372   /* if left is same as result */
5373   if (sameRegs (AOP (result), AOP (left)))
5374     {
5375       for (; size--; offset++)
5376         {
5377           if (AOP_TYPE (right) == AOP_LIT)
5378             {
5379               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5380                 continue;
5381               else if (bytelit == 0)
5382                 aopPut (AOP (result), zero, offset);
5383               else if (IS_AOP_PREG (result))
5384                 {
5385                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5386                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5387                   aopPut (AOP (result), "a", offset);
5388                 }
5389               else
5390                 emitcode ("anl", "%s,%s",
5391                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5392                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5393             }
5394           else
5395             {
5396               if (AOP_TYPE (left) == AOP_ACC)
5397                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5398               else
5399                 {
5400                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5401                   if (IS_AOP_PREG (result))
5402                     {
5403                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5404                       aopPut (AOP (result), "a", offset);
5405
5406                     }
5407                   else
5408                     emitcode ("anl", "%s,a",
5409                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5410                 }
5411             }
5412         }
5413     }
5414   else
5415     {
5416       // left & result in different registers
5417       if (AOP_TYPE (result) == AOP_CRY)
5418         {
5419           // result = bit
5420           // if(size), result in bit
5421           // if(!size && ifx), conditional oper: if(left & right)
5422           symbol *tlbl = newiTempLabel (NULL);
5423           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5424           if (size)
5425             emitcode ("setb", "c");
5426           while (sizer--)
5427             {
5428               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5429                 emitcode ("anl", "a,%s",
5430                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5431               } else {
5432                 if (AOP_TYPE(left)==AOP_ACC) {
5433                   emitcode("mov", "b,a");
5434                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5435                   emitcode("anl", "a,b");
5436                 }else {
5437                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5438                   emitcode ("anl", "a,%s",
5439                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5440                 }
5441               }
5442               emitcode ("jnz", "%05d$", tlbl->key + 100);
5443               offset++;
5444             }
5445           if (size)
5446             {
5447               CLRC;
5448               emitcode ("", "%05d$:", tlbl->key + 100);
5449               outBitC (result);
5450             }
5451           else if (ifx)
5452             jmpTrueOrFalse (ifx, tlbl);
5453         }
5454       else
5455         {
5456           for (; (size--); offset++)
5457             {
5458               // normal case
5459               // result = left & right
5460               if (AOP_TYPE (right) == AOP_LIT)
5461                 {
5462                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5463                     {
5464                       aopPut (AOP (result),
5465                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5466                               offset);
5467                       continue;
5468                     }
5469                   else if (bytelit == 0)
5470                     {
5471                       aopPut (AOP (result), zero, offset);
5472                       continue;
5473                     }
5474                   D (emitcode (";", "better literal AND."););
5475                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5476                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5477                                                     FALSE, FALSE, FALSE));
5478
5479                 }
5480               else
5481                 {
5482                   // faster than result <- left, anl result,right
5483                   // and better if result is SFR
5484                   if (AOP_TYPE (left) == AOP_ACC)
5485                     {
5486                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5487                                                        FALSE, FALSE, FALSE));
5488                     }
5489                   else
5490                     {
5491                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5492                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5493                       {
5494                           emitcode("mov", "b,a");
5495                           rOp = "b";
5496                       }
5497                         
5498                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5499                       emitcode ("anl", "a,%s", rOp);
5500                     }                   
5501                 }
5502               aopPut (AOP (result), "a", offset);
5503             }
5504         }
5505     }
5506
5507 release:
5508   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5509   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5510   freeAsmop (result, NULL, ic, TRUE);
5511 }
5512
5513
5514 /*-----------------------------------------------------------------*/
5515 /* genOr  - code for or                                            */
5516 /*-----------------------------------------------------------------*/
5517 static void
5518 genOr (iCode * ic, iCode * ifx)
5519 {
5520   operand *left, *right, *result;
5521   int size, offset = 0;
5522   unsigned long lit = 0L;
5523   bool     pushResult;
5524
5525   D (emitcode (";", "genOr "););
5526
5527   AOP_OP_3_NOFATAL (ic, pushResult);
5528   AOP_SET_LOCALS (ic);
5529
5530   if (pushResult)
5531   {
5532       genFarFarLogicOp(ic, "orl");
5533       return;
5534   }
5535
5536
5537 #ifdef DEBUG_TYPE
5538   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5539             AOP_TYPE (result),
5540             AOP_TYPE (left), AOP_TYPE (right));
5541   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5542             AOP_SIZE (result),
5543             AOP_SIZE (left), AOP_SIZE (right));
5544 #endif
5545
5546   /* if left is a literal & right is not then exchange them */
5547   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5548 #ifdef LOGIC_OPS_BROKEN
5549    || AOP_NEEDSACC (left) // I think this is a net loss now.
5550 #endif      
5551       )
5552     {
5553       operand *tmp = right;
5554       right = left;
5555       left = tmp;
5556     }
5557
5558   /* if result = right then exchange them */
5559   if (sameRegs (AOP (result), AOP (right)))
5560     {
5561       operand *tmp = right;
5562       right = left;
5563       left = tmp;
5564     }
5565
5566   /* if right is bit then exchange them */
5567   if (AOP_TYPE (right) == AOP_CRY &&
5568       AOP_TYPE (left) != AOP_CRY)
5569     {
5570       operand *tmp = right;
5571       right = left;
5572       left = tmp;
5573     }
5574   if (AOP_TYPE (right) == AOP_LIT)
5575     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5576
5577   size = AOP_SIZE (result);
5578
5579   // if(bit | yy)
5580   // xx = bit | yy;
5581   if (AOP_TYPE (left) == AOP_CRY)
5582     {
5583       if (AOP_TYPE (right) == AOP_LIT)
5584         {
5585           // c = bit & literal;
5586           if (lit)
5587             {
5588               // lit != 0 => result = 1
5589               if (AOP_TYPE (result) == AOP_CRY)
5590                 {
5591                   if (size)
5592                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5593                   else if (ifx)
5594                     continueIfTrue (ifx);
5595                   goto release;
5596                 }
5597               emitcode ("setb", "c");
5598             }
5599           else
5600             {
5601               // lit == 0 => result = left
5602               if (size && sameRegs (AOP (result), AOP (left)))
5603                 goto release;
5604               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5605             }
5606         }
5607       else
5608         {
5609           if (AOP_TYPE (right) == AOP_CRY)
5610             {
5611               // c = bit | bit;
5612               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5613               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5614             }
5615           else
5616             {
5617               // c = bit | val;
5618               symbol *tlbl = newiTempLabel (NULL);
5619               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5620                 emitcode ("setb", "c");
5621               emitcode ("jb", "%s,%05d$",
5622                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
5623               toBoolean (right);
5624               emitcode ("jnz", "%05d$", tlbl->key + 100);
5625               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5626                 {
5627                   jmpTrueOrFalse (ifx, tlbl);
5628                   goto release;
5629                 }
5630               else
5631                 {
5632                   CLRC;
5633                   emitcode ("", "%05d$:", tlbl->key + 100);
5634                 }
5635             }
5636         }
5637       // bit = c
5638       // val = c
5639       if (size)
5640         outBitC (result);
5641       // if(bit | ...)
5642       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5643         genIfxJump (ifx, "c");
5644       goto release;
5645     }
5646
5647   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5648   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5649   if ((AOP_TYPE (right) == AOP_LIT) &&
5650       (AOP_TYPE (result) == AOP_CRY) &&
5651       (AOP_TYPE (left) != AOP_CRY))
5652     {
5653       if (lit)
5654         {
5655           // result = 1
5656           if (size)
5657             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5658           else
5659             continueIfTrue (ifx);
5660           goto release;
5661         }
5662       else
5663         {
5664           // lit = 0, result = boolean(left)
5665           if (size)
5666             emitcode ("setb", "c");
5667           toBoolean (right);
5668           if (size)
5669             {
5670               symbol *tlbl = newiTempLabel (NULL);
5671               emitcode ("jnz", "%05d$", tlbl->key + 100);
5672               CLRC;
5673               emitcode ("", "%05d$:", tlbl->key + 100);
5674             }
5675           else
5676             {
5677               genIfxJump (ifx, "a");
5678               goto release;
5679             }
5680         }
5681       outBitC (result);
5682       goto release;
5683     }
5684
5685   /* if left is same as result */
5686   if (sameRegs (AOP (result), AOP (left)))
5687     {
5688       for (; size--; offset++)
5689         {
5690           if (AOP_TYPE (right) == AOP_LIT)
5691             {
5692               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5693                 {
5694                   continue;
5695                 }
5696               else
5697                 {
5698                   if (IS_AOP_PREG (left))
5699                     {
5700                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5701                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5702                       aopPut (AOP (result), "a", offset);
5703                     }
5704                   else
5705                     {
5706                       emitcode ("orl", "%s,%s",
5707                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5708                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5709                     }
5710                 }
5711             }
5712           else
5713             {
5714               if (AOP_TYPE (left) == AOP_ACC)
5715                 {
5716                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5717                 }
5718               else
5719                 {
5720                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5721                   if (IS_AOP_PREG (left))
5722                     {
5723                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5724                       aopPut (AOP (result), "a", offset);
5725                     }
5726                   else
5727                     {
5728                       emitcode ("orl", "%s,a",
5729                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5730                     }
5731                 }
5732             }
5733         }
5734     }
5735   else
5736     {
5737       // left & result in different registers
5738       if (AOP_TYPE (result) == AOP_CRY)
5739         {
5740           // result = bit
5741           // if(size), result in bit
5742           // if(!size && ifx), conditional oper: if(left | right)
5743           symbol *tlbl = newiTempLabel (NULL);
5744           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5745           if (size)
5746             emitcode ("setb", "c");
5747           while (sizer--)
5748             {
5749               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5750                 emitcode ("orl", "a,%s",
5751                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5752               } else {
5753                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5754                 emitcode ("orl", "a,%s",
5755                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5756               }
5757               emitcode ("jnz", "%05d$", tlbl->key + 100);
5758               offset++;
5759             }
5760           if (size)
5761             {
5762               CLRC;
5763               emitcode ("", "%05d$:", tlbl->key + 100);
5764               outBitC (result);
5765             }
5766           else if (ifx)
5767             jmpTrueOrFalse (ifx, tlbl);
5768         }
5769       else
5770         {
5771             _startLazyDPSEvaluation();
5772           for (; (size--); offset++)
5773             {
5774               // normal case
5775               // result = left & right
5776               if (AOP_TYPE (right) == AOP_LIT)
5777                 {
5778                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5779                     {
5780                       aopPut (AOP (result),
5781                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5782                               offset);
5783                       continue;
5784                     }
5785                   D (emitcode (";", "better literal OR."););
5786                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5787                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
5788                                                     FALSE, FALSE, FALSE));
5789
5790                 }
5791               else
5792                 {
5793                   // faster than result <- left, anl result,right
5794                   // and better if result is SFR
5795                   if (AOP_TYPE (left) == AOP_ACC)
5796                     {
5797                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
5798                                                        FALSE, FALSE, FALSE));
5799                     }
5800                   else
5801                     {
5802                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5803                         
5804                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5805                       {
5806                           emitcode("mov", "b,a");
5807                           rOp = "b";
5808                       }
5809                         
5810                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5811                       emitcode ("orl", "a,%s", rOp);
5812                     }
5813                 }
5814               aopPut (AOP (result), "a", offset);
5815             }
5816             _endLazyDPSEvaluation();
5817         }
5818     }
5819
5820 release:
5821   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5822   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5823   freeAsmop (result, NULL, ic, TRUE);
5824 }
5825
5826 /*-----------------------------------------------------------------*/
5827 /* genXor - code for xclusive or                                   */
5828 /*-----------------------------------------------------------------*/
5829 static void
5830 genXor (iCode * ic, iCode * ifx)
5831 {
5832   operand *left, *right, *result;
5833   int size, offset = 0;
5834   unsigned long lit = 0L;
5835   bool pushResult;
5836
5837   D (emitcode (";", "genXor "););
5838
5839   AOP_OP_3_NOFATAL (ic, pushResult);
5840   AOP_SET_LOCALS (ic);
5841
5842   if (pushResult)
5843   {
5844       genFarFarLogicOp(ic, "xrl");
5845       return;
5846   }  
5847
5848 #ifdef DEBUG_TYPE
5849   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5850             AOP_TYPE (result),
5851             AOP_TYPE (left), AOP_TYPE (right));
5852   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5853             AOP_SIZE (result),
5854             AOP_SIZE (left), AOP_SIZE (right));
5855 #endif
5856
5857   /* if left is a literal & right is not ||
5858      if left needs acc & right does not */
5859   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
5860 #ifdef LOGIC_OPS_BROKEN      
5861       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
5862 #endif
5863      )
5864     {
5865       operand *tmp = right;
5866       right = left;
5867       left = tmp;
5868     }
5869
5870   /* if result = right then exchange them */
5871   if (sameRegs (AOP (result), AOP (right)))
5872     {
5873       operand *tmp = right;
5874       right = left;
5875       left = tmp;
5876     }
5877
5878   /* if right is bit then exchange them */
5879   if (AOP_TYPE (right) == AOP_CRY &&
5880       AOP_TYPE (left) != AOP_CRY)
5881     {
5882       operand *tmp = right;
5883       right = left;
5884       left = tmp;
5885     }
5886   if (AOP_TYPE (right) == AOP_LIT)
5887     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5888
5889   size = AOP_SIZE (result);
5890
5891   // if(bit ^ yy)
5892   // xx = bit ^ yy;
5893   if (AOP_TYPE (left) == AOP_CRY)
5894     {
5895       if (AOP_TYPE (right) == AOP_LIT)
5896         {
5897           // c = bit & literal;
5898           if (lit >> 1)
5899             {
5900               // lit>>1  != 0 => result = 1
5901               if (AOP_TYPE (result) == AOP_CRY)
5902                 {
5903                   if (size)
5904                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5905                   else if (ifx)
5906                     continueIfTrue (ifx);
5907                   goto release;
5908                 }
5909               emitcode ("setb", "c");
5910             }
5911           else
5912             {
5913               // lit == (0 or 1)
5914               if (lit == 0)
5915                 {
5916                   // lit == 0, result = left
5917                   if (size && sameRegs (AOP (result), AOP (left)))
5918                     goto release;
5919                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5920                 }
5921               else
5922                 {
5923                   // lit == 1, result = not(left)
5924                   if (size && sameRegs (AOP (result), AOP (left)))
5925                     {
5926                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5927                       goto release;
5928                     }
5929                   else
5930                     {
5931                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5932                       emitcode ("cpl", "c");
5933                     }
5934                 }
5935             }
5936
5937         }
5938       else
5939         {
5940           // right != literal
5941           symbol *tlbl = newiTempLabel (NULL);
5942           if (AOP_TYPE (right) == AOP_CRY)
5943             {
5944               // c = bit ^ bit;
5945               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5946             }
5947           else
5948             {
5949               int sizer = AOP_SIZE (right);
5950               // c = bit ^ val
5951               // if val>>1 != 0, result = 1
5952               emitcode ("setb", "c");
5953               while (sizer)
5954                 {
5955                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
5956                   if (sizer == 1)
5957                     // test the msb of the lsb
5958                     emitcode ("anl", "a,#0xfe");
5959                   emitcode ("jnz", "%05d$", tlbl->key + 100);
5960                   sizer--;
5961                 }
5962               // val = (0,1)
5963               emitcode ("rrc", "a");
5964             }
5965           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5966           emitcode ("cpl", "c");
5967           emitcode ("", "%05d$:", (tlbl->key + 100));
5968         }
5969       // bit = c
5970       // val = c
5971       if (size)
5972         outBitC (result);
5973       // if(bit | ...)
5974       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5975         genIfxJump (ifx, "c");
5976       goto release;
5977     }
5978
5979   if (sameRegs (AOP (result), AOP (left)))
5980     {
5981       /* if left is same as result */
5982       for (; size--; offset++)
5983         {
5984           if (AOP_TYPE (right) == AOP_LIT)
5985             {
5986               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5987                 continue;
5988               else if (IS_AOP_PREG (left))
5989                 {
5990                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5991                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5992                   aopPut (AOP (result), "a", offset);
5993                 }
5994               else
5995                 emitcode ("xrl", "%s,%s",
5996                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5997                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5998             }
5999           else
6000             {
6001               if (AOP_TYPE (left) == AOP_ACC)
6002                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6003               else
6004                 {
6005                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6006                   if (IS_AOP_PREG (left))
6007                     {
6008                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6009                       aopPut (AOP (result), "a", offset);
6010                     }
6011                   else
6012                     emitcode ("xrl", "%s,a",
6013                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6014                 }
6015             }
6016         }
6017     }
6018   else
6019     {
6020       // left & result in different registers
6021       if (AOP_TYPE (result) == AOP_CRY)
6022         {
6023           // result = bit
6024           // if(size), result in bit
6025           // if(!size && ifx), conditional oper: if(left ^ right)
6026           symbol *tlbl = newiTempLabel (NULL);
6027           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6028           if (size)
6029             emitcode ("setb", "c");
6030           while (sizer--)
6031             {
6032               if ((AOP_TYPE (right) == AOP_LIT) &&
6033                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6034                 {
6035                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6036                 }
6037               else
6038                 {
6039                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6040                     emitcode ("xrl", "a,%s",
6041                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6042                   } else {
6043                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6044                     emitcode ("xrl", "a,%s",
6045                               aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6046                   }
6047                 }
6048               emitcode ("jnz", "%05d$", tlbl->key + 100);
6049               offset++;
6050             }
6051           if (size)
6052             {
6053               CLRC;
6054               emitcode ("", "%05d$:", tlbl->key + 100);
6055               outBitC (result);
6056             }
6057           else if (ifx)
6058             jmpTrueOrFalse (ifx, tlbl);
6059         }
6060       else
6061         for (; (size--); offset++)
6062           {
6063             // normal case
6064             // result = left & right
6065             if (AOP_TYPE (right) == AOP_LIT)
6066               {
6067                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6068                   {
6069                     aopPut (AOP (result),
6070                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6071                             offset);
6072                     continue;
6073                   }
6074                 D (emitcode (";", "better literal XOR.");
6075                   );
6076                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6077                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6078                                                   FALSE, FALSE, FALSE));
6079               }
6080             else
6081               {
6082                 // faster than result <- left, anl result,right
6083                 // and better if result is SFR
6084                 if (AOP_TYPE (left) == AOP_ACC)
6085                   {
6086                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6087                                                      FALSE, FALSE, FALSE));
6088                   }
6089                 else
6090                   {
6091                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6092                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6093                       {
6094                           emitcode("mov", "b,a");
6095                           rOp = "b";
6096                       }
6097                         
6098                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6099                       emitcode ("xrl", "a,%s", rOp);
6100                   }
6101               }
6102             aopPut (AOP (result), "a", offset);
6103           }
6104     }
6105
6106 release:
6107   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6108   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6109   freeAsmop (result, NULL, ic, TRUE);
6110 }
6111
6112 /*-----------------------------------------------------------------*/
6113 /* genInline - write the inline code out                           */
6114 /*-----------------------------------------------------------------*/
6115 static void
6116 genInline (iCode * ic)
6117 {
6118   char *buffer, *bp, *bp1;
6119
6120   D (emitcode (";", "genInline ");
6121     );
6122
6123   _G.inLine += (!options.asmpeep);
6124
6125   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6126   strcpy (buffer, IC_INLINE (ic));
6127
6128   /* emit each line as a code */
6129   while (*bp)
6130     {
6131       if (*bp == '\n')
6132         {
6133           *bp++ = '\0';
6134           emitcode (bp1, "");
6135           bp1 = bp;
6136         }
6137       else
6138         {
6139           if (*bp == ':')
6140             {
6141               bp++;
6142               *bp = '\0';
6143               bp++;
6144               emitcode (bp1, "");
6145               bp1 = bp;
6146             }
6147           else
6148             bp++;
6149         }
6150     }
6151   if (bp1 != bp)
6152     emitcode (bp1, "");
6153   /*     emitcode("",buffer); */
6154   _G.inLine -= (!options.asmpeep);
6155 }
6156
6157 /*-----------------------------------------------------------------*/
6158 /* genRRC - rotate right with carry                                */
6159 /*-----------------------------------------------------------------*/
6160 static void
6161 genRRC (iCode * ic)
6162 {
6163   operand *left, *result;
6164   int size, offset = 0;
6165   char *l;
6166
6167   D (emitcode (";", "genRRC ");
6168     );
6169
6170   /* rotate right with carry */
6171   left = IC_LEFT (ic);
6172   result = IC_RESULT (ic);
6173   aopOp (left, ic, FALSE, FALSE);
6174   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6175
6176   /* move it to the result */
6177   size = AOP_SIZE (result);
6178   offset = size - 1;
6179   CLRC;
6180
6181   _startLazyDPSEvaluation ();
6182   while (size--)
6183     {
6184       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6185       MOVA (l);
6186       emitcode ("rrc", "a");
6187       if (AOP_SIZE (result) > 1)
6188         aopPut (AOP (result), "a", offset--);
6189     }
6190   _endLazyDPSEvaluation ();
6191
6192   /* now we need to put the carry into the
6193      highest order byte of the result */
6194   if (AOP_SIZE (result) > 1)
6195     {
6196       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6197       MOVA (l);
6198     }
6199   emitcode ("mov", "acc.7,c");
6200   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6201   freeAsmop (left, NULL, ic, TRUE);
6202   freeAsmop (result, NULL, ic, TRUE);
6203 }
6204
6205 /*-----------------------------------------------------------------*/
6206 /* genRLC - generate code for rotate left with carry               */
6207 /*-----------------------------------------------------------------*/
6208 static void
6209 genRLC (iCode * ic)
6210 {
6211   operand *left, *result;
6212   int size, offset = 0;
6213   char *l;
6214
6215   D (emitcode (";", "genRLC ");
6216     );
6217
6218   /* rotate right with carry */
6219   left = IC_LEFT (ic);
6220   result = IC_RESULT (ic);
6221   aopOp (left, ic, FALSE, FALSE);
6222   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6223
6224   /* move it to the result */
6225   size = AOP_SIZE (result);
6226   offset = 0;
6227   if (size--)
6228     {
6229       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6230       MOVA (l);
6231       emitcode ("add", "a,acc");
6232       if (AOP_SIZE (result) > 1)
6233         {
6234           aopPut (AOP (result), "a", offset++);
6235         }
6236
6237       _startLazyDPSEvaluation ();
6238       while (size--)
6239         {
6240           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6241           MOVA (l);
6242           emitcode ("rlc", "a");
6243           if (AOP_SIZE (result) > 1)
6244             aopPut (AOP (result), "a", offset++);
6245         }
6246       _endLazyDPSEvaluation ();
6247     }
6248   /* now we need to put the carry into the
6249      highest order byte of the result */
6250   if (AOP_SIZE (result) > 1)
6251     {
6252       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6253       MOVA (l);
6254     }
6255   emitcode ("mov", "acc.0,c");
6256   aopPut (AOP (result), "a", 0);
6257   freeAsmop (left, NULL, ic, TRUE);
6258   freeAsmop (result, NULL, ic, TRUE);
6259 }
6260
6261 /*-----------------------------------------------------------------*/
6262 /* genGetHbit - generates code get highest order bit               */
6263 /*-----------------------------------------------------------------*/
6264 static void
6265 genGetHbit (iCode * ic)
6266 {
6267   operand *left, *result;
6268   left = IC_LEFT (ic);
6269   result = IC_RESULT (ic);
6270   aopOp (left, ic, FALSE, FALSE);
6271   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6272
6273   D (emitcode (";", "genGetHbit ");
6274     );
6275
6276   /* get the highest order byte into a */
6277   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6278   if (AOP_TYPE (result) == AOP_CRY)
6279     {
6280       emitcode ("rlc", "a");
6281       outBitC (result);
6282     }
6283   else
6284     {
6285       emitcode ("rl", "a");
6286       emitcode ("anl", "a,#0x01");
6287       outAcc (result);
6288     }
6289
6290
6291   freeAsmop (left, NULL, ic, TRUE);
6292   freeAsmop (result, NULL, ic, TRUE);
6293 }
6294
6295 /*-----------------------------------------------------------------*/
6296 /* AccRol - rotate left accumulator by known count                 */
6297 /*-----------------------------------------------------------------*/
6298 static void
6299 AccRol (int shCount)
6300 {
6301   shCount &= 0x0007;            // shCount : 0..7
6302
6303   switch (shCount)
6304     {
6305     case 0:
6306       break;
6307     case 1:
6308       emitcode ("rl", "a");
6309       break;
6310     case 2:
6311       emitcode ("rl", "a");
6312       emitcode ("rl", "a");
6313       break;
6314     case 3:
6315       emitcode ("swap", "a");
6316       emitcode ("rr", "a");
6317       break;
6318     case 4:
6319       emitcode ("swap", "a");
6320       break;
6321     case 5:
6322       emitcode ("swap", "a");
6323       emitcode ("rl", "a");
6324       break;
6325     case 6:
6326       emitcode ("rr", "a");
6327       emitcode ("rr", "a");
6328       break;
6329     case 7:
6330       emitcode ("rr", "a");
6331       break;
6332     }
6333 }
6334
6335 /*-----------------------------------------------------------------*/
6336 /* AccLsh - left shift accumulator by known count                  */
6337 /*-----------------------------------------------------------------*/
6338 static void
6339 AccLsh (int shCount)
6340 {
6341   if (shCount != 0)
6342     {
6343       if (shCount == 1)
6344         emitcode ("add", "a,acc");
6345       else if (shCount == 2)
6346         {
6347           emitcode ("add", "a,acc");
6348           emitcode ("add", "a,acc");
6349         }
6350       else
6351         {
6352           /* rotate left accumulator */
6353           AccRol (shCount);
6354           /* and kill the lower order bits */
6355           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6356         }
6357     }
6358 }
6359
6360 /*-----------------------------------------------------------------*/
6361 /* AccRsh - right shift accumulator by known count                 */
6362 /*-----------------------------------------------------------------*/
6363 static void
6364 AccRsh (int shCount)
6365 {
6366   if (shCount != 0)
6367     {
6368       if (shCount == 1)
6369         {
6370           CLRC;
6371           emitcode ("rrc", "a");
6372         }
6373       else
6374         {
6375           /* rotate right accumulator */
6376           AccRol (8 - shCount);
6377           /* and kill the higher order bits */
6378           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6379         }
6380     }
6381 }
6382
6383 #ifdef BETTER_LITERAL_SHIFT
6384 /*-----------------------------------------------------------------*/
6385 /* AccSRsh - signed right shift accumulator by known count                 */
6386 /*-----------------------------------------------------------------*/
6387 static void
6388 AccSRsh (int shCount)
6389 {
6390   symbol *tlbl;
6391   if (shCount != 0)
6392     {
6393       if (shCount == 1)
6394         {
6395           emitcode ("mov", "c,acc.7");
6396           emitcode ("rrc", "a");
6397         }
6398       else if (shCount == 2)
6399         {
6400           emitcode ("mov", "c,acc.7");
6401           emitcode ("rrc", "a");
6402           emitcode ("mov", "c,acc.7");
6403           emitcode ("rrc", "a");
6404         }
6405       else
6406         {
6407           tlbl = newiTempLabel (NULL);
6408           /* rotate right accumulator */
6409           AccRol (8 - shCount);
6410           /* and kill the higher order bits */
6411           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6412           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6413           emitcode ("orl", "a,#0x%02x",
6414                     (unsigned char) ~SRMask[shCount]);
6415           emitcode ("", "%05d$:", tlbl->key + 100);
6416         }
6417     }
6418 }
6419 #endif
6420
6421 #ifdef BETTER_LITERAL_SHIFT
6422 /*-----------------------------------------------------------------*/
6423 /* shiftR1Left2Result - shift right one byte from left to result   */
6424 /*-----------------------------------------------------------------*/
6425 static void
6426 shiftR1Left2Result (operand * left, int offl,
6427                     operand * result, int offr,
6428                     int shCount, int sign)
6429 {
6430   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6431   /* shift right accumulator */
6432   if (sign)
6433     AccSRsh (shCount);
6434   else
6435     AccRsh (shCount);
6436   aopPut (AOP (result), "a", offr);
6437 }
6438 #endif
6439
6440 #ifdef BETTER_LITERAL_SHIFT
6441 /*-----------------------------------------------------------------*/
6442 /* shiftL1Left2Result - shift left one byte from left to result    */
6443 /*-----------------------------------------------------------------*/
6444 static void
6445 shiftL1Left2Result (operand * left, int offl,
6446                     operand * result, int offr, int shCount)
6447 {
6448   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6449   /* shift left accumulator */
6450   AccLsh (shCount);
6451   aopPut (AOP (result), "a", offr);
6452 }
6453 #endif
6454
6455 #ifdef BETTER_LITERAL_SHIFT
6456 /*-----------------------------------------------------------------*/
6457 /* movLeft2Result - move byte from left to result                  */
6458 /*-----------------------------------------------------------------*/
6459 static void
6460 movLeft2Result (operand * left, int offl,
6461                 operand * result, int offr, int sign)
6462 {
6463   char *l;
6464   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6465   {
6466       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6467
6468       if (*l == '@' && (IS_AOP_PREG (result)))
6469       {
6470           emitcode ("mov", "a,%s", l);
6471           aopPut (AOP (result), "a", offr);
6472       }
6473       else
6474       {
6475           if (!sign)
6476           {
6477             aopPut (AOP (result), l, offr);
6478           }
6479           else
6480             {
6481               /* MSB sign in acc.7 ! */
6482               if (getDataSize (left) == offl + 1)
6483                 {
6484                   emitcode ("mov", "a,%s", l);
6485                   aopPut (AOP (result), "a", offr);
6486                 }
6487             }
6488       }
6489   }
6490 }
6491 #endif
6492
6493 #ifdef BETTER_LITERAL_SHIFT
6494 /*-----------------------------------------------------------------*/
6495 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6496 /*-----------------------------------------------------------------*/
6497 static void
6498 AccAXRrl1 (char *x)
6499 {
6500   emitcode ("rrc", "a");
6501   emitcode ("xch", "a,%s", x);
6502   emitcode ("rrc", "a");
6503   emitcode ("xch", "a,%s", x);
6504 }
6505 #endif
6506
6507 #ifdef BETTER_LITERAL_SHIFT
6508 //REMOVE ME!!!
6509 /*-----------------------------------------------------------------*/
6510 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6511 /*-----------------------------------------------------------------*/
6512 static void
6513 AccAXLrl1 (char *x)
6514 {
6515   emitcode ("xch", "a,%s", x);
6516   emitcode ("rlc", "a");
6517   emitcode ("xch", "a,%s", x);
6518   emitcode ("rlc", "a");
6519 }
6520 #endif
6521
6522 #ifdef BETTER_LITERAL_SHIFT
6523 /*-----------------------------------------------------------------*/
6524 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6525 /*-----------------------------------------------------------------*/
6526 static void
6527 AccAXLsh1 (char *x)
6528 {
6529   emitcode ("xch", "a,%s", x);
6530   emitcode ("add", "a,acc");
6531   emitcode ("xch", "a,%s", x);
6532   emitcode ("rlc", "a");
6533 }
6534 #endif
6535
6536 #ifdef BETTER_LITERAL_SHIFT
6537 /*-----------------------------------------------------------------*/
6538 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6539 /*-----------------------------------------------------------------*/
6540 static void
6541 AccAXLsh (char *x, int shCount)
6542 {
6543   switch (shCount)
6544     {
6545     case 0:
6546       break;
6547     case 1:
6548       AccAXLsh1 (x);
6549       break;
6550     case 2:
6551       AccAXLsh1 (x);
6552       AccAXLsh1 (x);
6553       break;
6554     case 3:
6555     case 4:
6556     case 5:                     // AAAAABBB:CCCCCDDD
6557
6558       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
6559
6560       emitcode ("anl", "a,#0x%02x",
6561                 SLMask[shCount]);       // BBB00000:CCCCCDDD
6562
6563       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
6564
6565       AccRol (shCount);         // DDDCCCCC:BBB00000
6566
6567       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
6568
6569       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
6570
6571       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
6572
6573       emitcode ("anl", "a,#0x%02x",
6574                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
6575
6576       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
6577
6578       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
6579
6580       break;
6581     case 6:                     // AAAAAABB:CCCCCCDD
6582       emitcode ("anl", "a,#0x%02x",
6583                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6584       emitcode ("mov", "c,acc.0");      // c = B
6585       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6586 #if 0
6587       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6588       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6589 #else
6590       emitcode("rrc","a"); 
6591       emitcode("xch","a,%s", x); 
6592       emitcode("rrc","a"); 
6593       emitcode("mov","c,acc.0"); //<< get correct bit 
6594       emitcode("xch","a,%s", x); 
6595
6596       emitcode("rrc","a"); 
6597       emitcode("xch","a,%s", x); 
6598       emitcode("rrc","a"); 
6599       emitcode("xch","a,%s", x); 
6600 #endif
6601       break;
6602     case 7:                     // a:x <<= 7
6603
6604       emitcode ("anl", "a,#0x%02x",
6605                 SRMask[shCount]);       // 0000000B:CCCCCCCD
6606
6607       emitcode ("mov", "c,acc.0");      // c = B
6608
6609       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
6610
6611       AccAXRrl1 (x);            // BCCCCCCC:D0000000
6612
6613       break;
6614     default:
6615       break;
6616     }
6617 }
6618 #endif
6619
6620 #ifdef BETTER_LITERAL_SHIFT
6621 //REMOVE ME!!!
6622 /*-----------------------------------------------------------------*/
6623 /* AccAXRsh - right shift a:x known count (0..7)                   */
6624 /*-----------------------------------------------------------------*/
6625 static void
6626 AccAXRsh (char *x, int shCount)
6627 {
6628   switch (shCount)
6629     {
6630     case 0:
6631       break;
6632     case 1:
6633       CLRC;
6634       AccAXRrl1 (x);            // 0->a:x
6635
6636       break;
6637     case 2:
6638       CLRC;
6639       AccAXRrl1 (x);            // 0->a:x
6640
6641       CLRC;
6642       AccAXRrl1 (x);            // 0->a:x
6643
6644       break;
6645     case 3:
6646     case 4:
6647     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6648
6649       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
6650
6651       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6652
6653       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6654
6655       emitcode ("anl", "a,#0x%02x",
6656                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6657
6658       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6659
6660       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6661
6662       emitcode ("anl", "a,#0x%02x",
6663                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6664
6665       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6666
6667       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6668
6669       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
6670
6671       break;
6672     case 6:                     // AABBBBBB:CCDDDDDD
6673
6674       emitcode ("mov", "c,acc.7");
6675       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6676
6677       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6678
6679       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6680
6681       emitcode ("anl", "a,#0x%02x",
6682                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6683
6684       break;
6685     case 7:                     // ABBBBBBB:CDDDDDDD
6686
6687       emitcode ("mov", "c,acc.7");      // c = A
6688
6689       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6690
6691       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6692
6693       emitcode ("anl", "a,#0x%02x",
6694                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6695
6696       break;
6697     default:
6698       break;
6699     }
6700 }
6701 #endif
6702
6703 #ifdef BETTER_LITERAL_SHIFT
6704 /*-----------------------------------------------------------------*/
6705 /* AccAXRshS - right shift signed a:x known count (0..7)           */
6706 /*-----------------------------------------------------------------*/
6707 static void
6708 AccAXRshS (char *x, int shCount)
6709 {
6710   symbol *tlbl;
6711   switch (shCount)
6712     {
6713     case 0:
6714       break;
6715     case 1:
6716       emitcode ("mov", "c,acc.7");
6717       AccAXRrl1 (x);            // s->a:x
6718
6719       break;
6720     case 2:
6721       emitcode ("mov", "c,acc.7");
6722       AccAXRrl1 (x);            // s->a:x
6723
6724       emitcode ("mov", "c,acc.7");
6725       AccAXRrl1 (x);            // s->a:x
6726
6727       break;
6728     case 3:
6729     case 4:
6730     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6731
6732       tlbl = newiTempLabel (NULL);
6733       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
6734
6735       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6736
6737       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6738
6739       emitcode ("anl", "a,#0x%02x",
6740                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6741
6742       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6743
6744       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6745
6746       emitcode ("anl", "a,#0x%02x",
6747                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6748
6749       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6750
6751       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6752
6753       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
6754
6755       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6756       emitcode ("orl", "a,#0x%02x",
6757                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
6758
6759       emitcode ("", "%05d$:", tlbl->key + 100);
6760       break;                    // SSSSAAAA:BBBCCCCC
6761
6762     case 6:                     // AABBBBBB:CCDDDDDD
6763
6764       tlbl = newiTempLabel (NULL);
6765       emitcode ("mov", "c,acc.7");
6766       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
6767
6768       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
6769
6770       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
6771
6772       emitcode ("anl", "a,#0x%02x",
6773                 SRMask[shCount]);       // 000000AA:BBBBBBCC
6774
6775       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6776       emitcode ("orl", "a,#0x%02x",
6777                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
6778
6779       emitcode ("", "%05d$:", tlbl->key + 100);
6780       break;
6781     case 7:                     // ABBBBBBB:CDDDDDDD
6782
6783       tlbl = newiTempLabel (NULL);
6784       emitcode ("mov", "c,acc.7");      // c = A
6785
6786       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
6787
6788       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
6789
6790       emitcode ("anl", "a,#0x%02x",
6791                 SRMask[shCount]);       // 0000000A:BBBBBBBC
6792
6793       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6794       emitcode ("orl", "a,#0x%02x",
6795                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
6796
6797       emitcode ("", "%05d$:", tlbl->key + 100);
6798       break;
6799     default:
6800       break;
6801     }
6802 }
6803 #endif
6804
6805 #ifdef BETTER_LITERAL_SHIFT
6806 static void
6807 _loadLeftIntoAx(char    **lsb, 
6808                 operand *left, 
6809                 operand *result,
6810                 int     offl,
6811                 int     offr)
6812 {
6813   // Get the initial value from left into a pair of registers.
6814   // MSB must be in A, LSB can be any register.
6815   //
6816   // If the result is held in registers, it is an optimization
6817   // if the LSB can be held in the register which will hold the,
6818   // result LSB since this saves us from having to copy it into
6819   // the result following AccAXLsh.
6820   //
6821   // If the result is addressed indirectly, this is not a gain.
6822   if (AOP_NEEDSACC(result))
6823   {
6824        char *leftByte;
6825        
6826        _startLazyDPSEvaluation();
6827       if (AOP_TYPE(left) == AOP_DPTR2)
6828        {
6829            // Get MSB in A.
6830            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
6831            // get LSB in DP2_RESULT_REG.
6832            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
6833            assert(!strcmp(leftByte, DP2_RESULT_REG));
6834        }
6835        else
6836        {
6837            // get LSB into DP2_RESULT_REG
6838            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
6839            if (strcmp(leftByte, DP2_RESULT_REG))
6840            {
6841                TR_AP("#7");
6842                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
6843            }
6844            // And MSB in A.
6845            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
6846            assert(strcmp(leftByte, DP2_RESULT_REG));
6847            MOVA(leftByte);
6848        }
6849        _endLazyDPSEvaluation();
6850        *lsb = DP2_RESULT_REG;
6851   }
6852   else
6853   {
6854       if (sameRegs (AOP (result), AOP (left)) &&
6855         ((offl + MSB16) == offr))
6856       {
6857           /* don't crash result[offr] */
6858           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
6859           emitcode ("xch", "a,%s", 
6860                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
6861       }
6862       else
6863       {
6864           movLeft2Result (left, offl, result, offr, 0);
6865           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
6866       }
6867       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
6868       assert(strcmp(*lsb,"a"));      
6869   }
6870 }
6871
6872 static void
6873 _storeAxResults(char    *lsb,
6874                 operand *result,
6875                 int     offr)
6876 {
6877   _startLazyDPSEvaluation();
6878   if (AOP_NEEDSACC(result))
6879   {
6880       /* We have to explicitly update the result LSB.
6881        */
6882       emitcode("xch","a,%s", lsb);
6883       aopPut(AOP(result), "a", offr);
6884       emitcode("mov","a,%s", lsb);
6885   }
6886   if (getDataSize (result) > 1)
6887   {
6888       aopPut (AOP (result), "a", offr + MSB16);
6889   }
6890   _endLazyDPSEvaluation();
6891 }
6892
6893 /*-----------------------------------------------------------------*/
6894 /* shiftL2Left2Result - shift left two bytes from left to result   */
6895 /*-----------------------------------------------------------------*/
6896 static void
6897 shiftL2Left2Result (operand * left, int offl,
6898                     operand * result, int offr, int shCount)
6899 {
6900   char *lsb;
6901
6902   _loadLeftIntoAx(&lsb, left, result, offl, offr);
6903   
6904   AccAXLsh (lsb, shCount);
6905   
6906   _storeAxResults(lsb, result, offr);
6907 }
6908 #endif
6909
6910 #ifdef BETTER_LITERAL_SHIFT
6911 /*-----------------------------------------------------------------*/
6912 /* shiftR2Left2Result - shift right two bytes from left to result  */
6913 /*-----------------------------------------------------------------*/
6914 static void
6915 shiftR2Left2Result (operand * left, int offl,
6916                     operand * result, int offr,
6917                     int shCount, int sign)
6918 {
6919   char *lsb;
6920   
6921   _loadLeftIntoAx(&lsb, left, result, offl, offr);
6922   
6923   /* a:x >> shCount (x = lsb(result)) */
6924   if (sign)
6925   {
6926      AccAXRshS(lsb, shCount);
6927   }
6928   else
6929   {
6930     AccAXRsh(lsb, shCount);
6931   }
6932   
6933   _storeAxResults(lsb, result, offr);
6934 }
6935 #endif
6936
6937 #if 0
6938 //REMOVE ME!!!
6939 /*-----------------------------------------------------------------*/
6940 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6941 /*-----------------------------------------------------------------*/
6942 static void
6943 shiftLLeftOrResult (operand * left, int offl,
6944                     operand * result, int offr, int shCount)
6945 {
6946   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6947   /* shift left accumulator */
6948   AccLsh (shCount);
6949   /* or with result */
6950   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6951   /* back to result */
6952   aopPut (AOP (result), "a", offr);
6953 }
6954 #endif
6955
6956 #if 0
6957 //REMOVE ME!!!
6958 /*-----------------------------------------------------------------*/
6959 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6960 /*-----------------------------------------------------------------*/
6961 static void
6962 shiftRLeftOrResult (operand * left, int offl,
6963                     operand * result, int offr, int shCount)
6964 {
6965   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6966   /* shift right accumulator */
6967   AccRsh (shCount);
6968   /* or with result */
6969   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
6970   /* back to result */
6971   aopPut (AOP (result), "a", offr);
6972 }
6973 #endif
6974
6975 #ifdef BETTER_LITERAL_SHIFT
6976 /*-----------------------------------------------------------------*/
6977 /* genlshOne - left shift a one byte quantity by known count       */
6978 /*-----------------------------------------------------------------*/
6979 static void
6980 genlshOne (operand * result, operand * left, int shCount)
6981 {
6982   D (emitcode (";", "genlshOne "););
6983   shiftL1Left2Result (left, LSB, result, LSB, shCount);
6984 }
6985 #endif
6986
6987 #ifdef BETTER_LITERAL_SHIFT
6988 /*-----------------------------------------------------------------*/
6989 /* genlshTwo - left shift two bytes by known amount != 0           */
6990 /*-----------------------------------------------------------------*/
6991 static void
6992 genlshTwo (operand * result, operand * left, int shCount)
6993 {
6994   int size;
6995
6996   D (emitcode (";", "genlshTwo "););
6997
6998   size = getDataSize (result);
6999
7000   /* if shCount >= 8 */
7001   if (shCount >= 8)
7002   {
7003       shCount -= 8;
7004
7005       _startLazyDPSEvaluation();
7006
7007       if (size > 1)
7008         {
7009           if (shCount)
7010           {
7011             _endLazyDPSEvaluation();
7012             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7013             aopPut (AOP (result), zero, LSB);       
7014           }
7015           else
7016           {
7017             movLeft2Result (left, LSB, result, MSB16, 0);
7018             aopPut (AOP (result), zero, LSB);
7019             _endLazyDPSEvaluation();
7020           }
7021         }
7022         else
7023         {
7024           aopPut (AOP (result), zero, LSB);
7025           _endLazyDPSEvaluation();
7026         }
7027   }
7028
7029   /*  1 <= shCount <= 7 */
7030   else
7031     {
7032       if (size == 1)
7033       {
7034         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7035       }
7036       else
7037       {
7038         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7039       }
7040     }
7041 }
7042 #endif
7043
7044 #if 0
7045 //REMOVE ME!!!
7046 /*-----------------------------------------------------------------*/
7047 /* shiftLLong - shift left one long from left to result            */
7048 /* offl = LSB or MSB16                                             */
7049 /*-----------------------------------------------------------------*/
7050 static void
7051 shiftLLong (operand * left, operand * result, int offr)
7052 {
7053   char *l;
7054   int size = AOP_SIZE (result);
7055
7056   if (size >= LSB + offr)
7057     {
7058       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7059       MOVA (l);
7060       emitcode ("add", "a,acc");
7061       if (sameRegs (AOP (left), AOP (result)) &&
7062           size >= MSB16 + offr && offr != LSB)
7063         emitcode ("xch", "a,%s",
7064                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7065       else
7066         aopPut (AOP (result), "a", LSB + offr);
7067     }
7068
7069   if (size >= MSB16 + offr)
7070     {
7071       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7072         {
7073           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7074           MOVA (l);
7075         }
7076       emitcode ("rlc", "a");
7077       if (sameRegs (AOP (left), AOP (result)) &&
7078           size >= MSB24 + offr && offr != LSB)
7079         emitcode ("xch", "a,%s",
7080                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7081       else
7082         aopPut (AOP (result), "a", MSB16 + offr);
7083     }
7084
7085   if (size >= MSB24 + offr)
7086     {
7087       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7088         {
7089           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7090           MOVA (l);
7091         }
7092       emitcode ("rlc", "a");
7093       if (sameRegs (AOP (left), AOP (result)) &&
7094           size >= MSB32 + offr && offr != LSB)
7095         emitcode ("xch", "a,%s",
7096                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7097       else
7098         aopPut (AOP (result), "a", MSB24 + offr);
7099     }
7100
7101   if (size > MSB32 + offr)
7102     {
7103       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7104         {
7105           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7106           MOVA (l);
7107         }
7108       emitcode ("rlc", "a");
7109       aopPut (AOP (result), "a", MSB32 + offr);
7110     }
7111   if (offr != LSB)
7112     aopPut (AOP (result), zero, LSB);
7113 }
7114 #endif
7115
7116 #if 0
7117 //REMOVE ME!!!
7118 /*-----------------------------------------------------------------*/
7119 /* genlshFour - shift four byte by a known amount != 0             */
7120 /*-----------------------------------------------------------------*/
7121 static void
7122 genlshFour (operand * result, operand * left, int shCount)
7123 {
7124   int size;
7125
7126   D (emitcode (";", "genlshFour ");
7127     );
7128
7129   size = AOP_SIZE (result);
7130
7131   /* if shifting more that 3 bytes */
7132   if (shCount >= 24)
7133     {
7134       shCount -= 24;
7135       if (shCount)
7136         /* lowest order of left goes to the highest
7137            order of the destination */
7138         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7139       else
7140         movLeft2Result (left, LSB, result, MSB32, 0);
7141       aopPut (AOP (result), zero, LSB);
7142       aopPut (AOP (result), zero, MSB16);
7143       aopPut (AOP (result), zero, MSB24);
7144       return;
7145     }
7146
7147   /* more than two bytes */
7148   else if (shCount >= 16)
7149     {
7150       /* lower order two bytes goes to higher order two bytes */
7151       shCount -= 16;
7152       /* if some more remaining */
7153       if (shCount)
7154         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7155       else
7156         {
7157           movLeft2Result (left, MSB16, result, MSB32, 0);
7158           movLeft2Result (left, LSB, result, MSB24, 0);
7159         }
7160       aopPut (AOP (result), zero, MSB16);
7161       aopPut (AOP (result), zero, LSB);
7162       return;
7163     }
7164
7165   /* if more than 1 byte */
7166   else if (shCount >= 8)
7167     {
7168       /* lower order three bytes goes to higher order  three bytes */
7169       shCount -= 8;
7170       if (size == 2)
7171         {
7172           if (shCount)
7173             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7174           else
7175             movLeft2Result (left, LSB, result, MSB16, 0);
7176         }
7177       else
7178         {                       /* size = 4 */
7179           if (shCount == 0)
7180             {
7181               movLeft2Result (left, MSB24, result, MSB32, 0);
7182               movLeft2Result (left, MSB16, result, MSB24, 0);
7183               movLeft2Result (left, LSB, result, MSB16, 0);
7184               aopPut (AOP (result), zero, LSB);
7185             }
7186           else if (shCount == 1)
7187             shiftLLong (left, result, MSB16);
7188           else
7189             {
7190               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7191               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7192               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7193               aopPut (AOP (result), zero, LSB);
7194             }
7195         }
7196     }
7197
7198   /* 1 <= shCount <= 7 */
7199   else if (shCount <= 2)
7200     {
7201       shiftLLong (left, result, LSB);
7202       if (shCount == 2)
7203         shiftLLong (result, result, LSB);
7204     }
7205   /* 3 <= shCount <= 7, optimize */
7206   else
7207     {
7208       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7209       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7210       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7211     }
7212 }
7213 #endif
7214
7215 #ifdef BETTER_LITERAL_SHIFT
7216 /*-----------------------------------------------------------------*/
7217 /* genLeftShiftLiteral - left shifting by known count              */
7218 /*-----------------------------------------------------------------*/
7219 static bool
7220 genLeftShiftLiteral (operand * left,
7221                      operand * right,
7222                      operand * result,
7223                      iCode * ic)
7224 {
7225   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7226   int size;
7227
7228   size = getSize (operandType (result));
7229
7230   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7231
7232   /* We only handle certain easy cases so far. */
7233   if ((shCount != 0)
7234    && (shCount < (size * 8))
7235    && (size != 1)
7236    && (size != 2))
7237   {
7238       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7239       return FALSE;
7240   }
7241
7242   freeAsmop (right, NULL, ic, TRUE);
7243
7244   aopOp(left, ic, FALSE, FALSE);
7245   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7246
7247 #if 1 // debug spew
7248   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7249   {
7250         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7251         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7252         {
7253            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7254         }
7255   }
7256   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7257   {
7258         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7259         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7260         {
7261            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7262         }       
7263   }  
7264 #endif
7265   
7266 #if VIEW_SIZE
7267   emitcode ("; shift left ", "result %d, left %d", size,
7268             AOP_SIZE (left));
7269 #endif
7270
7271   /* I suppose that the left size >= result size */
7272   if (shCount == 0)
7273   {
7274         _startLazyDPSEvaluation();
7275         while (size--)
7276         {
7277           movLeft2Result (left, size, result, size, 0);
7278         }
7279         _endLazyDPSEvaluation();
7280   }
7281   else if (shCount >= (size * 8))
7282   {
7283     _startLazyDPSEvaluation();
7284     while (size--)
7285     {
7286       aopPut (AOP (result), zero, size);
7287     }
7288     _endLazyDPSEvaluation();
7289   }
7290   else
7291   {
7292       switch (size)
7293         {
7294         case 1:
7295           genlshOne (result, left, shCount);
7296           break;
7297
7298         case 2:
7299           genlshTwo (result, left, shCount);
7300           break;
7301 #if 0
7302         case 4:
7303           genlshFour (result, left, shCount);
7304           break;
7305 #endif
7306         default:
7307           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7308           break;
7309         }
7310     }
7311   freeAsmop (left, NULL, ic, TRUE);
7312   freeAsmop (result, NULL, ic, TRUE);
7313   return TRUE;
7314 }
7315 #endif
7316
7317 /*-----------------------------------------------------------------*/
7318 /* genLeftShift - generates code for left shifting                 */
7319 /*-----------------------------------------------------------------*/
7320 static void
7321 genLeftShift (iCode * ic)
7322 {
7323   operand *left, *right, *result;
7324   int size, offset;
7325   char *l;
7326   symbol *tlbl, *tlbl1;
7327
7328   D (emitcode (";", "genLeftShift "););
7329
7330   right = IC_RIGHT (ic);
7331   left = IC_LEFT (ic);
7332   result = IC_RESULT (ic);
7333
7334   aopOp (right, ic, FALSE, FALSE);
7335
7336
7337 #ifdef BETTER_LITERAL_SHIFT
7338   /* if the shift count is known then do it
7339      as efficiently as possible */
7340   if (AOP_TYPE (right) == AOP_LIT)
7341     {
7342       if (genLeftShiftLiteral (left, right, result, ic))
7343       {
7344         return;
7345       }
7346     }
7347 #endif
7348
7349   /* shift count is unknown then we have to form
7350      a loop get the loop count in B : Note: we take
7351      only the lower order byte since shifting
7352      more that 32 bits make no sense anyway, ( the
7353      largest size of an object can be only 32 bits ) */
7354
7355   if (AOP_TYPE (right) == AOP_LIT)
7356   {
7357       /* Really should be handled by genLeftShiftLiteral,
7358        * but since I'm too lazy to fix that today, at least we can make
7359        * some small improvement.
7360        */
7361        emitcode("mov", "b,#0x%02x",
7362                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7363   }
7364   else
7365   {
7366         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7367         emitcode ("inc", "b");
7368   }
7369   freeAsmop (right, NULL, ic, TRUE);
7370   aopOp (left, ic, FALSE, FALSE);
7371   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7372
7373   /* now move the left to the result if they are not the
7374      same */
7375   if (!sameRegs (AOP (left), AOP (result)) &&
7376       AOP_SIZE (result) > 1)
7377     {
7378
7379       size = AOP_SIZE (result);
7380       offset = 0;
7381       _startLazyDPSEvaluation ();
7382       while (size--)
7383         {
7384           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7385           if (*l == '@' && (IS_AOP_PREG (result)))
7386             {
7387
7388               emitcode ("mov", "a,%s", l);
7389               aopPut (AOP (result), "a", offset);
7390             }
7391           else
7392             aopPut (AOP (result), l, offset);
7393           offset++;
7394         }
7395       _endLazyDPSEvaluation ();
7396     }
7397
7398   tlbl = newiTempLabel (NULL);
7399   size = AOP_SIZE (result);
7400   offset = 0;
7401   tlbl1 = newiTempLabel (NULL);
7402
7403   /* if it is only one byte then */
7404   if (size == 1)
7405     {
7406       symbol *tlbl1 = newiTempLabel (NULL);
7407
7408       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7409       MOVA (l);
7410       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7411       emitcode ("", "%05d$:", tlbl->key + 100);
7412       emitcode ("add", "a,acc");
7413       emitcode ("", "%05d$:", tlbl1->key + 100);
7414       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7415       aopPut (AOP (result), "a", 0);
7416       goto release;
7417     }
7418
7419   reAdjustPreg (AOP (result));
7420
7421   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7422   emitcode ("", "%05d$:", tlbl->key + 100);
7423   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7424   MOVA (l);
7425   emitcode ("add", "a,acc");
7426   aopPut (AOP (result), "a", offset++);
7427   _startLazyDPSEvaluation ();
7428   while (--size)
7429     {
7430       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7431       MOVA (l);
7432       emitcode ("rlc", "a");
7433       aopPut (AOP (result), "a", offset++);
7434     }
7435   _endLazyDPSEvaluation ();
7436   reAdjustPreg (AOP (result));
7437
7438   emitcode ("", "%05d$:", tlbl1->key + 100);
7439   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7440 release:
7441   freeAsmop (left, NULL, ic, TRUE);
7442   freeAsmop (result, NULL, ic, TRUE);
7443 }
7444
7445 #ifdef BETTER_LITERAL_SHIFT
7446 /*-----------------------------------------------------------------*/
7447 /* genrshOne - right shift a one byte quantity by known count      */
7448 /*-----------------------------------------------------------------*/
7449 static void
7450 genrshOne (operand * result, operand * left,
7451            int shCount, int sign)
7452 {
7453   D (emitcode (";", "genrshOne"););
7454   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7455 }
7456 #endif
7457
7458 #ifdef BETTER_LITERAL_SHIFT
7459 /*-----------------------------------------------------------------*/
7460 /* genrshTwo - right shift two bytes by known amount != 0          */
7461 /*-----------------------------------------------------------------*/
7462 static void
7463 genrshTwo (operand * result, operand * left,
7464            int shCount, int sign)
7465 {
7466   D (emitcode (";", "genrshTwo"););
7467
7468   /* if shCount >= 8 */
7469   if (shCount >= 8)
7470     {
7471       shCount -= 8;
7472       _startLazyDPSEvaluation();
7473       if (shCount)
7474       {
7475         shiftR1Left2Result (left, MSB16, result, LSB,
7476                             shCount, sign);
7477       }                     
7478       else
7479       {
7480         movLeft2Result (left, MSB16, result, LSB, sign);
7481       }
7482       addSign (result, MSB16, sign);
7483       _endLazyDPSEvaluation();
7484     }
7485
7486   /*  1 <= shCount <= 7 */
7487   else
7488   {
7489     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7490   }
7491 }
7492 #endif
7493
7494 #if 0
7495 //REMOVE ME!!!
7496 /*-----------------------------------------------------------------*/
7497 /* shiftRLong - shift right one long from left to result           */
7498 /* offl = LSB or MSB16                                             */
7499 /*-----------------------------------------------------------------*/
7500 static void
7501 shiftRLong (operand * left, int offl,
7502             operand * result, int sign)
7503 {
7504   int isSameRegs=sameRegs(AOP(left),AOP(result));
7505
7506   if (isSameRegs && offl>1) {
7507     // we are in big trouble, but this shouldn't happen
7508     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7509   }
7510
7511   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7512   
7513   if (offl==MSB16) {
7514     // shift is > 8
7515     if (sign) {
7516       emitcode ("rlc", "a");
7517       emitcode ("subb", "a,acc");
7518       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7519     } else {
7520       aopPut (AOP(result), zero, MSB32);
7521     }
7522   }
7523
7524   if (!sign) {
7525     emitcode ("clr", "c");
7526   } else {
7527     emitcode ("mov", "c,acc.7");
7528   }
7529
7530   emitcode ("rrc", "a");
7531
7532   if (isSameRegs && offl==MSB16) {
7533     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7534   } else {
7535     aopPut (AOP (result), "a", MSB32);
7536     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7537   }
7538
7539   emitcode ("rrc", "a");
7540   if (isSameRegs && offl==1) {
7541     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7542   } else {
7543     aopPut (AOP (result), "a", MSB24);
7544     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7545   }
7546   emitcode ("rrc", "a");
7547   aopPut (AOP (result), "a", MSB16 - offl);
7548
7549   if (offl == LSB)
7550     {
7551       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7552       emitcode ("rrc", "a");
7553       aopPut (AOP (result), "a", LSB);
7554     }
7555 }
7556 #endif
7557
7558 #if 0
7559 //REMOVE ME!!!
7560 /*-----------------------------------------------------------------*/
7561 /* genrshFour - shift four byte by a known amount != 0             */
7562 /*-----------------------------------------------------------------*/
7563 static void
7564 genrshFour (operand * result, operand * left,
7565             int shCount, int sign)
7566 {
7567   D (emitcode (";", "genrshFour");
7568     );
7569
7570   /* if shifting more that 3 bytes */
7571   if (shCount >= 24)
7572     {
7573       shCount -= 24;
7574       if (shCount)
7575         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7576       else
7577         movLeft2Result (left, MSB32, result, LSB, sign);
7578       addSign (result, MSB16, sign);
7579     }
7580   else if (shCount >= 16)
7581     {
7582       shCount -= 16;
7583       if (shCount)
7584         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7585       else
7586         {
7587           movLeft2Result (left, MSB24, result, LSB, 0);
7588           movLeft2Result (left, MSB32, result, MSB16, sign);
7589         }
7590       addSign (result, MSB24, sign);
7591     }
7592   else if (shCount >= 8)
7593     {
7594       shCount -= 8;
7595       if (shCount == 1)
7596         shiftRLong (left, MSB16, result, sign);
7597       else if (shCount == 0)
7598         {
7599           movLeft2Result (left, MSB16, result, LSB, 0);
7600           movLeft2Result (left, MSB24, result, MSB16, 0);
7601           movLeft2Result (left, MSB32, result, MSB24, sign);
7602           addSign (result, MSB32, sign);
7603         }
7604       else
7605         {
7606           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7607           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7608           /* the last shift is signed */
7609           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7610           addSign (result, MSB32, sign);
7611         }
7612     }
7613   else
7614     {                           /* 1 <= shCount <= 7 */
7615       if (shCount <= 2)
7616         {
7617           shiftRLong (left, LSB, result, sign);
7618           if (shCount == 2)
7619             shiftRLong (result, LSB, result, sign);
7620         }
7621       else
7622         {
7623           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7624           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7625           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7626         }
7627     }
7628 }
7629 #endif
7630
7631 #ifdef BETTER_LITERAL_SHIFT
7632 /*-----------------------------------------------------------------*/
7633 /* genRightShiftLiteral - right shifting by known count            */
7634 /*-----------------------------------------------------------------*/
7635 static bool
7636 genRightShiftLiteral (operand * left,
7637                       operand * right,
7638                       operand * result,
7639                       iCode * ic,
7640                       int sign)
7641 {
7642   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7643   int size;
7644
7645   size = getSize (operandType (result));
7646
7647   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7648
7649   /* We only handle certain easy cases so far. */
7650   if ((shCount != 0)
7651    && (shCount < (size * 8))
7652    && (size != 1)
7653    && (size != 2))
7654   {
7655       D(emitcode (";", "genRightShiftLiteral wimping out"););   
7656       return FALSE;
7657   }
7658
7659   freeAsmop (right, NULL, ic, TRUE);
7660
7661   aopOp (left, ic, FALSE, FALSE);
7662   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7663
7664 #if VIEW_SIZE
7665   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7666             AOP_SIZE (left));
7667 #endif
7668
7669   /* test the LEFT size !!! */
7670
7671   /* I suppose that the left size >= result size */
7672   if (shCount == 0)
7673   {
7674       size = getDataSize (result);
7675       _startLazyDPSEvaluation();
7676       while (size--)
7677       {
7678         movLeft2Result (left, size, result, size, 0);
7679       }
7680       _endLazyDPSEvaluation();
7681   }
7682   else if (shCount >= (size * 8))
7683     {
7684       if (sign)
7685       {
7686         /* get sign in acc.7 */
7687         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
7688       }
7689       addSign (result, LSB, sign);
7690     }
7691   else
7692     {
7693       switch (size)
7694         {
7695         case 1:
7696           genrshOne (result, left, shCount, sign);
7697           break;
7698
7699         case 2:
7700           genrshTwo (result, left, shCount, sign);
7701           break;
7702 #if 0
7703         case 4:
7704           genrshFour (result, left, shCount, sign);
7705           break;
7706 #endif    
7707         default:
7708           break;
7709         }
7710
7711       freeAsmop (left, NULL, ic, TRUE);
7712       freeAsmop (result, NULL, ic, TRUE);
7713     }
7714     return TRUE;
7715 }
7716 #endif
7717
7718 /*-----------------------------------------------------------------*/
7719 /* genSignedRightShift - right shift of signed number              */
7720 /*-----------------------------------------------------------------*/
7721 static void
7722 genSignedRightShift (iCode * ic)
7723 {
7724   operand *right, *left, *result;
7725   int size, offset;
7726   char *l;
7727   symbol *tlbl, *tlbl1;
7728
7729   D (emitcode (";", "genSignedRightShift "););
7730
7731   /* we do it the hard way put the shift count in b
7732      and loop thru preserving the sign */
7733
7734   right = IC_RIGHT (ic);
7735   left = IC_LEFT (ic);
7736   result = IC_RESULT (ic);
7737
7738   aopOp (right, ic, FALSE, FALSE);
7739
7740 #ifdef BETTER_LITERAL_SHIFT
7741   if (AOP_TYPE (right) == AOP_LIT)
7742     {
7743       if (genRightShiftLiteral (left, right, result, ic, 1))
7744       {
7745         return;
7746       }
7747     }
7748 #endif
7749   /* shift count is unknown then we have to form
7750      a loop get the loop count in B : Note: we take
7751      only the lower order byte since shifting
7752      more that 32 bits make no sense anyway, ( the
7753      largest size of an object can be only 32 bits ) */
7754
7755   if (AOP_TYPE (right) == AOP_LIT)
7756   {
7757       /* Really should be handled by genRightShiftLiteral,
7758        * but since I'm too lazy to fix that today, at least we can make
7759        * some small improvement.
7760        */
7761        emitcode("mov", "b,#0x%02x",
7762                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7763   }
7764   else
7765   {
7766         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7767         emitcode ("inc", "b");
7768   }
7769   freeAsmop (right, NULL, ic, TRUE);
7770   aopOp (left, ic, FALSE, FALSE);
7771   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7772
7773   /* now move the left to the result if they are not the
7774      same */
7775   if (!sameRegs (AOP (left), AOP (result)) &&
7776       AOP_SIZE (result) > 1)
7777     {
7778
7779       size = AOP_SIZE (result);
7780       offset = 0;
7781       _startLazyDPSEvaluation ();
7782       while (size--)
7783         {
7784           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7785           if (*l == '@' && IS_AOP_PREG (result))
7786             {
7787
7788               emitcode ("mov", "a,%s", l);
7789               aopPut (AOP (result), "a", offset);
7790             }
7791           else
7792             aopPut (AOP (result), l, offset);
7793           offset++;
7794         }
7795       _endLazyDPSEvaluation ();
7796     }
7797
7798   /* mov the highest order bit to OVR */
7799   tlbl = newiTempLabel (NULL);
7800   tlbl1 = newiTempLabel (NULL);
7801
7802   size = AOP_SIZE (result);
7803   offset = size - 1;
7804   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
7805   emitcode ("rlc", "a");
7806   emitcode ("mov", "ov,c");
7807   /* if it is only one byte then */
7808   if (size == 1)
7809     {
7810       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7811       MOVA (l);
7812       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7813       emitcode ("", "%05d$:", tlbl->key + 100);
7814       emitcode ("mov", "c,ov");
7815       emitcode ("rrc", "a");
7816       emitcode ("", "%05d$:", tlbl1->key + 100);
7817       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7818       aopPut (AOP (result), "a", 0);
7819       goto release;
7820     }
7821
7822   reAdjustPreg (AOP (result));
7823   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7824   emitcode ("", "%05d$:", tlbl->key + 100);
7825   emitcode ("mov", "c,ov");
7826   _startLazyDPSEvaluation ();
7827   while (size--)
7828     {
7829       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7830       MOVA (l);
7831       emitcode ("rrc", "a");
7832       aopPut (AOP (result), "a", offset--);
7833     }
7834   _endLazyDPSEvaluation ();
7835   reAdjustPreg (AOP (result));
7836   emitcode ("", "%05d$:", tlbl1->key + 100);
7837   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7838
7839 release:
7840   freeAsmop (left, NULL, ic, TRUE);
7841   freeAsmop (result, NULL, ic, TRUE);
7842 }
7843
7844 /*-----------------------------------------------------------------*/
7845 /* genRightShift - generate code for right shifting                */
7846 /*-----------------------------------------------------------------*/
7847 static void
7848 genRightShift (iCode * ic)
7849 {
7850   operand *right, *left, *result;
7851   sym_link *retype;
7852   int size, offset;
7853   char *l;
7854   symbol *tlbl, *tlbl1;
7855
7856   D (emitcode (";", "genRightShift "););
7857
7858   /* if signed then we do it the hard way preserve the
7859      sign bit moving it inwards */
7860   retype = getSpec (operandType (IC_RESULT (ic)));
7861
7862   if (!SPEC_USIGN (retype))
7863     {
7864       genSignedRightShift (ic);
7865       return;
7866     }
7867
7868   /* signed & unsigned types are treated the same : i.e. the
7869      signed is NOT propagated inwards : quoting from the
7870      ANSI - standard : "for E1 >> E2, is equivalent to division
7871      by 2**E2 if unsigned or if it has a non-negative value,
7872      otherwise the result is implementation defined ", MY definition
7873      is that the sign does not get propagated */
7874
7875   right = IC_RIGHT (ic);
7876   left = IC_LEFT (ic);
7877   result = IC_RESULT (ic);
7878
7879   aopOp (right, ic, FALSE, FALSE);
7880
7881 #ifdef BETTER_LITERAL_SHIFT
7882   /* if the shift count is known then do it
7883      as efficiently as possible */
7884   if (AOP_TYPE (right) == AOP_LIT)
7885     {
7886       if (genRightShiftLiteral (left, right, result, ic, 0))
7887       {
7888         return;
7889       }
7890     }
7891 #endif
7892
7893   /* shift count is unknown then we have to form
7894      a loop get the loop count in B : Note: we take
7895      only the lower order byte since shifting
7896      more that 32 bits make no sense anyway, ( the
7897      largest size of an object can be only 32 bits ) */
7898   
7899   if (AOP_TYPE (right) == AOP_LIT)
7900   {
7901       /* Really should be handled by genRightShiftLiteral,
7902        * but since I'm too lazy to fix that today, at least we can make
7903        * some small improvement.
7904        */
7905        emitcode("mov", "b,#0x%02x",
7906                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7907   }
7908   else
7909   {
7910         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7911         emitcode ("inc", "b");
7912   }
7913   freeAsmop (right, NULL, ic, TRUE);
7914   aopOp (left, ic, FALSE, FALSE);
7915   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7916
7917   /* now move the left to the result if they are not the
7918      same */
7919   if (!sameRegs (AOP (left), AOP (result)) &&
7920       AOP_SIZE (result) > 1)
7921     {
7922
7923       size = AOP_SIZE (result);
7924       offset = 0;
7925       _startLazyDPSEvaluation ();
7926       while (size--)
7927         {
7928           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7929           if (*l == '@' && IS_AOP_PREG (result))
7930             {
7931
7932               emitcode ("mov", "a,%s", l);
7933               aopPut (AOP (result), "a", offset);
7934             }
7935           else
7936             aopPut (AOP (result), l, offset);
7937           offset++;
7938         }
7939       _endLazyDPSEvaluation ();
7940     }
7941
7942   tlbl = newiTempLabel (NULL);
7943   tlbl1 = newiTempLabel (NULL);
7944   size = AOP_SIZE (result);
7945   offset = size - 1;
7946
7947   /* if it is only one byte then */
7948   if (size == 1)
7949     {
7950       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7951       MOVA (l);
7952       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7953       emitcode ("", "%05d$:", tlbl->key + 100);
7954       CLRC;
7955       emitcode ("rrc", "a");
7956       emitcode ("", "%05d$:", tlbl1->key + 100);
7957       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7958       aopPut (AOP (result), "a", 0);
7959       goto release;
7960     }
7961
7962   reAdjustPreg (AOP (result));
7963   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7964   emitcode ("", "%05d$:", tlbl->key + 100);
7965   CLRC;
7966   _startLazyDPSEvaluation ();
7967   while (size--)
7968     {
7969       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7970       MOVA (l);
7971       emitcode ("rrc", "a");
7972       aopPut (AOP (result), "a", offset--);
7973     }
7974   _endLazyDPSEvaluation ();
7975   reAdjustPreg (AOP (result));
7976
7977   emitcode ("", "%05d$:", tlbl1->key + 100);
7978   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7979
7980 release:
7981   freeAsmop (left, NULL, ic, TRUE);
7982   freeAsmop (result, NULL, ic, TRUE);
7983 }
7984
7985 /*-----------------------------------------------------------------*/
7986 /* genUnpackBits - generates code for unpacking bits               */
7987 /*-----------------------------------------------------------------*/
7988 static void
7989 genUnpackBits (operand * result, char *rname, int ptype)
7990 {
7991   int shCnt;
7992   int rlen = 0;
7993   sym_link *etype;
7994   int offset = 0;
7995
7996   D (emitcode (";", "genUnpackBits ");
7997     );
7998
7999   etype = getSpec (operandType (result));
8000
8001   /* read the first byte  */
8002   switch (ptype)
8003     {
8004
8005     case POINTER:
8006     case IPOINTER:
8007       emitcode ("mov", "a,@%s", rname);
8008       break;
8009
8010     case PPOINTER:
8011       emitcode ("movx", "a,@%s", rname);
8012       break;
8013
8014     case FPOINTER:
8015       emitcode ("movx", "a,@dptr");
8016       break;
8017
8018     case CPOINTER:
8019       emitcode ("clr", "a");
8020       emitcode ("movc", "a,@a+dptr");
8021       break;
8022
8023     case GPOINTER:
8024       emitcode ("lcall", "__gptrget");
8025       break;
8026     }
8027
8028   /* if we have bitdisplacement then it fits   */
8029   /* into this byte completely or if length is */
8030   /* less than a byte                          */
8031   if ((shCnt = SPEC_BSTR (etype)) ||
8032       (SPEC_BLEN (etype) <= 8))
8033     {
8034
8035       /* shift right acc */
8036       AccRsh (shCnt);
8037
8038       emitcode ("anl", "a,#0x%02x",
8039                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8040       aopPut (AOP (result), "a", offset);
8041       return;
8042     }
8043
8044   /* bit field did not fit in a byte  */
8045   rlen = SPEC_BLEN (etype) - 8;
8046   aopPut (AOP (result), "a", offset++);
8047
8048   while (1)
8049     {
8050
8051       switch (ptype)
8052         {
8053         case POINTER:
8054         case IPOINTER:
8055           emitcode ("inc", "%s", rname);
8056           emitcode ("mov", "a,@%s", rname);
8057           break;
8058
8059         case PPOINTER:
8060           emitcode ("inc", "%s", rname);
8061           emitcode ("movx", "a,@%s", rname);
8062           break;
8063
8064         case FPOINTER:
8065           emitcode ("inc", "dptr");
8066           emitcode ("movx", "a,@dptr");
8067           break;
8068
8069         case CPOINTER:
8070           emitcode ("clr", "a");
8071           emitcode ("inc", "dptr");
8072           emitcode ("movc", "a,@a+dptr");
8073           break;
8074
8075         case GPOINTER:
8076           emitcode ("inc", "dptr");
8077           emitcode ("lcall", "__gptrget");
8078           break;
8079         }
8080
8081       rlen -= 8;
8082       /* if we are done */
8083       if (rlen < 8)
8084         break;
8085
8086       aopPut (AOP (result), "a", offset++);
8087
8088     }
8089
8090   if (rlen)
8091     {
8092       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8093       aopPut (AOP (result), "a", offset);
8094     }
8095
8096   return;
8097 }
8098
8099
8100 /*-----------------------------------------------------------------*/
8101 /* genDataPointerGet - generates code when ptr offset is known     */
8102 /*-----------------------------------------------------------------*/
8103 static void
8104 genDataPointerGet (operand * left,
8105                    operand * result,
8106                    iCode * ic)
8107 {
8108   char *l;
8109   char buffer[256];
8110   int size, offset = 0;
8111   aopOp (result, ic, TRUE, FALSE);
8112
8113   /* get the string representation of the name */
8114   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8115   size = AOP_SIZE (result);
8116   _startLazyDPSEvaluation ();
8117   while (size--)
8118     {
8119       if (offset)
8120         sprintf (buffer, "(%s + %d)", l + 1, offset);
8121       else
8122         sprintf (buffer, "%s", l + 1);
8123       aopPut (AOP (result), buffer, offset++);
8124     }
8125   _endLazyDPSEvaluation ();
8126
8127   freeAsmop (left, NULL, ic, TRUE);
8128   freeAsmop (result, NULL, ic, TRUE);
8129 }
8130
8131 /*-----------------------------------------------------------------*/
8132 /* genNearPointerGet - emitcode for near pointer fetch             */
8133 /*-----------------------------------------------------------------*/
8134 static void
8135 genNearPointerGet (operand * left,
8136                    operand * result,
8137                    iCode * ic)
8138 {
8139   asmop *aop = NULL;
8140   regs *preg = NULL;
8141   char *rname;
8142   sym_link *rtype, *retype, *letype;
8143   sym_link *ltype = operandType (left);
8144   char buffer[80];
8145
8146   rtype = operandType (result);
8147   retype = getSpec (rtype);
8148   letype = getSpec (ltype);
8149
8150   aopOp (left, ic, FALSE, FALSE);
8151
8152   /* if left is rematerialisable and
8153      result is not bit variable type and
8154      the left is pointer to data space i.e
8155      lower 128 bytes of space */
8156   if (AOP_TYPE (left) == AOP_IMMD &&
8157       !IS_BITVAR (retype) &&
8158       !IS_BITVAR (letype) &&
8159       DCL_TYPE (ltype) == POINTER)
8160     {
8161       genDataPointerGet (left, result, ic);
8162       return;
8163     }
8164
8165   /* if the value is already in a pointer register
8166      then don't need anything more */
8167   if (!AOP_INPREG (AOP (left)))
8168     {
8169       /* otherwise get a free pointer register */
8170       aop = newAsmop (0);
8171       preg = getFreePtr (ic, &aop, FALSE);
8172       emitcode ("mov", "%s,%s",
8173                 preg->name,
8174                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8175       rname = preg->name;
8176     }
8177   else
8178     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8179
8180   freeAsmop (left, NULL, ic, TRUE);
8181   aopOp (result, ic, FALSE, FALSE);
8182
8183   /* if bitfield then unpack the bits */
8184   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8185     genUnpackBits (result, rname, POINTER);
8186   else
8187     {
8188       /* we have can just get the values */
8189       int size = AOP_SIZE (result);
8190       int offset = 0;
8191
8192       while (size--)
8193         {
8194           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8195             {
8196
8197               emitcode ("mov", "a,@%s", rname);
8198               aopPut (AOP (result), "a", offset);
8199             }
8200           else
8201             {
8202               sprintf (buffer, "@%s", rname);
8203               aopPut (AOP (result), buffer, offset);
8204             }
8205           offset++;
8206           if (size)
8207             emitcode ("inc", "%s", rname);
8208         }
8209     }
8210
8211   /* now some housekeeping stuff */
8212   if (aop)
8213     {
8214       /* we had to allocate for this iCode */
8215       freeAsmop (NULL, aop, ic, TRUE);
8216     }
8217   else
8218     {
8219       /* we did not allocate which means left
8220          already in a pointer register, then
8221          if size > 0 && this could be used again
8222          we have to point it back to where it
8223          belongs */
8224       if (AOP_SIZE (result) > 1 &&
8225           !OP_SYMBOL (left)->remat &&
8226           (OP_SYMBOL (left)->liveTo > ic->seq ||
8227            ic->depth))
8228         {
8229           int size = AOP_SIZE (result) - 1;
8230           while (size--)
8231             emitcode ("dec", "%s", rname);
8232         }
8233     }
8234
8235   /* done */
8236   freeAsmop (result, NULL, ic, TRUE);
8237
8238 }
8239
8240 /*-----------------------------------------------------------------*/
8241 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8242 /*-----------------------------------------------------------------*/
8243 static void
8244 genPagedPointerGet (operand * left,
8245                     operand * result,
8246                     iCode * ic)
8247 {
8248   asmop *aop = NULL;
8249   regs *preg = NULL;
8250   char *rname;
8251   sym_link *rtype, *retype, *letype;
8252
8253   rtype = operandType (result);
8254   retype = getSpec (rtype);
8255   letype = getSpec (operandType (left));
8256   aopOp (left, ic, FALSE, FALSE);
8257
8258   /* if the value is already in a pointer register
8259      then don't need anything more */
8260   if (!AOP_INPREG (AOP (left)))
8261     {
8262       /* otherwise get a free pointer register */
8263       aop = newAsmop (0);
8264       preg = getFreePtr (ic, &aop, FALSE);
8265       emitcode ("mov", "%s,%s",
8266                 preg->name,
8267                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8268       rname = preg->name;
8269     }
8270   else
8271     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8272
8273   freeAsmop (left, NULL, ic, TRUE);
8274   aopOp (result, ic, FALSE, FALSE);
8275
8276   /* if bitfield then unpack the bits */
8277   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8278     genUnpackBits (result, rname, PPOINTER);
8279   else
8280     {
8281       /* we have can just get the values */
8282       int size = AOP_SIZE (result);
8283       int offset = 0;
8284
8285       while (size--)
8286         {
8287
8288           emitcode ("movx", "a,@%s", rname);
8289           aopPut (AOP (result), "a", offset);
8290
8291           offset++;
8292
8293           if (size)
8294             emitcode ("inc", "%s", rname);
8295         }
8296     }
8297
8298   /* now some housekeeping stuff */
8299   if (aop)
8300     {
8301       /* we had to allocate for this iCode */
8302       freeAsmop (NULL, aop, ic, TRUE);
8303     }
8304   else
8305     {
8306       /* we did not allocate which means left
8307          already in a pointer register, then
8308          if size > 0 && this could be used again
8309          we have to point it back to where it
8310          belongs */
8311       if (AOP_SIZE (result) > 1 &&
8312           !OP_SYMBOL (left)->remat &&
8313           (OP_SYMBOL (left)->liveTo > ic->seq ||
8314            ic->depth))
8315         {
8316           int size = AOP_SIZE (result) - 1;
8317           while (size--)
8318             emitcode ("dec", "%s", rname);
8319         }
8320     }
8321
8322   /* done */
8323   freeAsmop (result, NULL, ic, TRUE);
8324
8325
8326 }
8327
8328 /*-----------------------------------------------------------------*/
8329 /* genFarPointerGet - gget value from far space                    */
8330 /*-----------------------------------------------------------------*/
8331 static void
8332 genFarPointerGet (operand * left,
8333                   operand * result, iCode * ic)
8334 {
8335   int size, offset;
8336   sym_link *retype = getSpec (operandType (result));
8337   sym_link *letype = getSpec (operandType (left));
8338   D (emitcode (";", "genFarPointerGet");
8339     );
8340
8341   aopOp (left, ic, FALSE, FALSE);
8342
8343   /* if the operand is already in dptr
8344      then we do nothing else we move the value to dptr */
8345   if (AOP_TYPE (left) != AOP_STR)
8346     {
8347       /* if this is remateriazable */
8348       if (AOP_TYPE (left) == AOP_IMMD)
8349         {
8350           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8351         }
8352       else
8353         {
8354           /* we need to get it byte by byte */
8355           _startLazyDPSEvaluation ();
8356           if (AOP_TYPE (left) != AOP_DPTR)
8357             {
8358               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8359               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8360               if (options.model == MODEL_FLAT24)
8361                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8362             }
8363           else
8364             {
8365               /* We need to generate a load to DPTR indirect through DPTR. */
8366               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8367                 );
8368               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8369               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8370               if (options.model == MODEL_FLAT24)
8371                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8372               emitcode ("pop", "dph");
8373               emitcode ("pop", "dpl");
8374             }
8375           _endLazyDPSEvaluation ();
8376         }
8377     }
8378   /* so dptr know contains the address */
8379   freeAsmop (left, NULL, ic, TRUE);
8380   aopOp (result, ic, FALSE, TRUE);
8381
8382   /* if bit then unpack */
8383   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8384     genUnpackBits (result, "dptr", FPOINTER);
8385   else
8386     {
8387       size = AOP_SIZE (result);
8388       offset = 0;
8389
8390       _startLazyDPSEvaluation ();
8391       while (size--)
8392         {
8393
8394           genSetDPTR (0);
8395           _flushLazyDPS ();
8396
8397           emitcode ("movx", "a,@dptr");
8398           if (size)
8399             emitcode ("inc", "dptr");
8400
8401           aopPut (AOP (result), "a", offset++);
8402         }
8403       _endLazyDPSEvaluation ();
8404     }
8405
8406   freeAsmop (result, NULL, ic, TRUE);
8407 }
8408
8409 /*-----------------------------------------------------------------*/
8410 /* emitcodePointerGet - gget value from code space                  */
8411 /*-----------------------------------------------------------------*/
8412 static void
8413 emitcodePointerGet (operand * left,
8414                     operand * result, iCode * ic)
8415 {
8416   int size, offset;
8417   sym_link *retype = getSpec (operandType (result));
8418
8419   aopOp (left, ic, FALSE, FALSE);
8420
8421   /* if the operand is already in dptr
8422      then we do nothing else we move the value to dptr */
8423   if (AOP_TYPE (left) != AOP_STR)
8424     {
8425       /* if this is remateriazable */
8426       if (AOP_TYPE (left) == AOP_IMMD)
8427         {
8428           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8429         }
8430       else
8431         {                       /* we need to get it byte by byte */
8432           _startLazyDPSEvaluation ();
8433           if (AOP_TYPE (left) != AOP_DPTR)
8434             {
8435               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8436               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8437               if (options.model == MODEL_FLAT24)
8438                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8439             }
8440           else
8441             {
8442               /* We need to generate a load to DPTR indirect through DPTR. */
8443               D (emitcode (";", "gencodePointerGet -- indirection special case.");
8444                 );
8445               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8446               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8447               if (options.model == MODEL_FLAT24)
8448                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8449               emitcode ("pop", "dph");
8450               emitcode ("pop", "dpl");
8451             }
8452           _endLazyDPSEvaluation ();
8453         }
8454     }
8455   /* so dptr know contains the address */
8456   freeAsmop (left, NULL, ic, TRUE);
8457   aopOp (result, ic, FALSE, TRUE);
8458
8459   /* if bit then unpack */
8460   if (IS_BITVAR (retype))
8461     genUnpackBits (result, "dptr", CPOINTER);
8462   else
8463     {
8464       size = AOP_SIZE (result);
8465       offset = 0;
8466
8467       _startLazyDPSEvaluation ();
8468       while (size--)
8469         {
8470           genSetDPTR (0);
8471           _flushLazyDPS ();
8472
8473           emitcode ("clr", "a");
8474           emitcode ("movc", "a,@a+dptr");
8475           if (size)
8476             emitcode ("inc", "dptr");
8477           aopPut (AOP (result), "a", offset++);
8478         }
8479       _endLazyDPSEvaluation ();
8480     }
8481
8482   freeAsmop (result, NULL, ic, TRUE);
8483 }
8484
8485 /*-----------------------------------------------------------------*/
8486 /* genGenPointerGet - gget value from generic pointer space        */
8487 /*-----------------------------------------------------------------*/
8488 static void
8489 genGenPointerGet (operand * left,
8490                   operand * result, iCode * ic)
8491 {
8492   int size, offset;
8493   sym_link *retype = getSpec (operandType (result));
8494   sym_link *letype = getSpec (operandType (left));
8495
8496   D (emitcode (";", "genGenPointerGet "); );
8497
8498   aopOp (left, ic, FALSE, TRUE);
8499
8500   /* if the operand is already in dptr
8501      then we do nothing else we move the value to dptr */
8502   if (AOP_TYPE (left) != AOP_STR)
8503     {
8504       /* if this is remateriazable */
8505       if (AOP_TYPE (left) == AOP_IMMD)
8506         {
8507           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8508           emitcode ("mov", "b,#%d", pointerCode (retype));
8509         }
8510       else
8511         {                       /* we need to get it byte by byte */
8512           _startLazyDPSEvaluation ();
8513           if (AOP(left)->type==AOP_DPTR2) {
8514             char *l;
8515             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8516             genSetDPTR(0);
8517             _flushLazyDPS();
8518             emitcode ("mov", "dpl,%s", l);
8519             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8520             genSetDPTR(0);
8521             _flushLazyDPS();
8522             emitcode ("mov", "dph,%s", l);
8523             if (options.model == MODEL_FLAT24) {
8524               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8525               genSetDPTR(0);
8526               _flushLazyDPS();
8527               emitcode ("mov", "dpx,%s", l);
8528               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8529             } else {
8530               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8531             }
8532           } else {
8533             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8534             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8535             if (options.model == MODEL_FLAT24) {
8536               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8537               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8538             } else {
8539               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8540             }
8541           }
8542           _endLazyDPSEvaluation ();
8543         }
8544     }
8545   /* so dptr know contains the address */
8546   freeAsmop (left, NULL, ic, TRUE);
8547   aopOp (result, ic, FALSE, TRUE);
8548
8549   /* if bit then unpack */
8550   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8551     genUnpackBits (result, "dptr", GPOINTER);
8552   else
8553     {
8554       size = AOP_SIZE (result);
8555       offset = 0;
8556
8557       while (size--)
8558         {
8559           emitcode ("lcall", "__gptrget");
8560           aopPut (AOP (result), "a", offset++);
8561           if (size)
8562             emitcode ("inc", "dptr");
8563         }
8564     }
8565
8566   freeAsmop (result, NULL, ic, TRUE);
8567 }
8568
8569 /*-----------------------------------------------------------------*/
8570 /* genPointerGet - generate code for pointer get                   */
8571 /*-----------------------------------------------------------------*/
8572 static void
8573 genPointerGet (iCode * ic)
8574 {
8575   operand *left, *result;
8576   sym_link *type, *etype;
8577   int p_type;
8578
8579   D (emitcode (";", "genPointerGet ");
8580     );
8581
8582   left = IC_LEFT (ic);
8583   result = IC_RESULT (ic);
8584
8585   /* depending on the type of pointer we need to
8586      move it to the correct pointer register */
8587   type = operandType (left);
8588   etype = getSpec (type);
8589   /* if left is of type of pointer then it is simple */
8590   if (IS_PTR (type) && !IS_FUNC (type->next))
8591     p_type = DCL_TYPE (type);
8592   else
8593     {
8594       /* we have to go by the storage class */
8595       p_type = PTR_TYPE (SPEC_OCLS (etype));
8596     }
8597
8598   /* now that we have the pointer type we assign
8599      the pointer values */
8600   switch (p_type)
8601     {
8602
8603     case POINTER:
8604     case IPOINTER:
8605       genNearPointerGet (left, result, ic);
8606       break;
8607
8608     case PPOINTER:
8609       genPagedPointerGet (left, result, ic);
8610       break;
8611
8612     case FPOINTER:
8613       genFarPointerGet (left, result, ic);
8614       break;
8615
8616     case CPOINTER:
8617       emitcodePointerGet (left, result, ic);
8618       break;
8619
8620     case GPOINTER:
8621       genGenPointerGet (left, result, ic);
8622       break;
8623     }
8624
8625 }
8626
8627 /*-----------------------------------------------------------------*/
8628 /* genPackBits - generates code for packed bit storage             */
8629 /*-----------------------------------------------------------------*/
8630 static void
8631 genPackBits (sym_link * etype,
8632              operand * right,
8633              char *rname, int p_type)
8634 {
8635   int shCount = 0;
8636   int offset = 0;
8637   int rLen = 0;
8638   int blen, bstr;
8639   char *l;
8640
8641   blen = SPEC_BLEN (etype);
8642   bstr = SPEC_BSTR (etype);
8643
8644   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8645   MOVA (l);
8646
8647   /* if the bit lenth is less than or    */
8648   /* it exactly fits a byte then         */
8649   if (SPEC_BLEN (etype) <= 8)
8650     {
8651       shCount = SPEC_BSTR (etype);
8652
8653       /* shift left acc */
8654       AccLsh (shCount);
8655
8656       if (SPEC_BLEN (etype) < 8)
8657         {                       /* if smaller than a byte */
8658
8659
8660           switch (p_type)
8661             {
8662             case POINTER:
8663               emitcode ("mov", "b,a");
8664               emitcode ("mov", "a,@%s", rname);
8665               break;
8666
8667             case FPOINTER:
8668               emitcode ("mov", "b,a");
8669               emitcode ("movx", "a,@dptr");
8670               break;
8671
8672             case GPOINTER:
8673               emitcode ("push", "b");
8674               emitcode ("push", "acc");
8675               emitcode ("lcall", "__gptrget");
8676               emitcode ("pop", "b");
8677               break;
8678             }
8679
8680           emitcode ("anl", "a,#0x%02x", (unsigned char)
8681                     ((unsigned char) (0xFF << (blen + bstr)) |
8682                      (unsigned char) (0xFF >> (8 - bstr))));
8683           emitcode ("orl", "a,b");
8684           if (p_type == GPOINTER)
8685             emitcode ("pop", "b");
8686         }
8687     }
8688
8689   switch (p_type)
8690     {
8691     case POINTER:
8692       emitcode ("mov", "@%s,a", rname);
8693       break;
8694
8695     case FPOINTER:
8696       emitcode ("movx", "@dptr,a");
8697       break;
8698
8699     case GPOINTER:
8700       emitcode ("lcall", "__gptrput");
8701       break;
8702     }
8703
8704   /* if we r done */
8705   if (SPEC_BLEN (etype) <= 8)
8706     return;
8707
8708   emitcode ("inc", "%s", rname);
8709   rLen = SPEC_BLEN (etype);
8710
8711   /* now generate for lengths greater than one byte */
8712   while (1)
8713     {
8714
8715       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
8716
8717       rLen -= 8;
8718       if (rLen < 8)
8719         break;
8720
8721       switch (p_type)
8722         {
8723         case POINTER:
8724           if (*l == '@')
8725             {
8726               MOVA (l);
8727               emitcode ("mov", "@%s,a", rname);
8728             }
8729           else
8730             emitcode ("mov", "@%s,%s", rname, l);
8731           break;
8732
8733         case FPOINTER:
8734           MOVA (l);
8735           emitcode ("movx", "@dptr,a");
8736           break;
8737
8738         case GPOINTER:
8739           MOVA (l);
8740           emitcode ("lcall", "__gptrput");
8741           break;
8742         }
8743       emitcode ("inc", "%s", rname);
8744     }
8745
8746   MOVA (l);
8747
8748   /* last last was not complete */
8749   if (rLen)
8750     {
8751       /* save the byte & read byte */
8752       switch (p_type)
8753         {
8754         case POINTER:
8755           emitcode ("mov", "b,a");
8756           emitcode ("mov", "a,@%s", rname);
8757           break;
8758
8759         case FPOINTER:
8760           emitcode ("mov", "b,a");
8761           emitcode ("movx", "a,@dptr");
8762           break;
8763
8764         case GPOINTER:
8765           emitcode ("push", "b");
8766           emitcode ("push", "acc");
8767           emitcode ("lcall", "__gptrget");
8768           emitcode ("pop", "b");
8769           break;
8770         }
8771
8772       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
8773       emitcode ("orl", "a,b");
8774     }
8775
8776   if (p_type == GPOINTER)
8777     emitcode ("pop", "b");
8778
8779   switch (p_type)
8780     {
8781
8782     case POINTER:
8783       emitcode ("mov", "@%s,a", rname);
8784       break;
8785
8786     case FPOINTER:
8787       emitcode ("movx", "@dptr,a");
8788       break;
8789
8790     case GPOINTER:
8791       emitcode ("lcall", "__gptrput");
8792       break;
8793     }
8794 }
8795 /*-----------------------------------------------------------------*/
8796 /* genDataPointerSet - remat pointer to data space                 */
8797 /*-----------------------------------------------------------------*/
8798 static void
8799 genDataPointerSet (operand * right,
8800                    operand * result,
8801                    iCode * ic)
8802 {
8803   int size, offset = 0;
8804   char *l, buffer[256];
8805
8806   aopOp (right, ic, FALSE, FALSE);
8807
8808   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
8809   size = AOP_SIZE (right);
8810   while (size--)
8811     {
8812       if (offset)
8813         sprintf (buffer, "(%s + %d)", l + 1, offset);
8814       else
8815         sprintf (buffer, "%s", l + 1);
8816       emitcode ("mov", "%s,%s", buffer,
8817                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
8818     }
8819
8820   freeAsmop (right, NULL, ic, TRUE);
8821   freeAsmop (result, NULL, ic, TRUE);
8822 }
8823
8824 /*-----------------------------------------------------------------*/
8825 /* genNearPointerSet - emitcode for near pointer put                */
8826 /*-----------------------------------------------------------------*/
8827 static void
8828 genNearPointerSet (operand * right,
8829                    operand * result,
8830                    iCode * ic)
8831 {
8832   asmop *aop = NULL;
8833   regs *preg = NULL;
8834   char *rname, *l;
8835   sym_link *retype, *letype;
8836   sym_link *ptype = operandType (result);
8837
8838   retype = getSpec (operandType (right));
8839   letype = getSpec (ptype);
8840
8841   aopOp (result, ic, FALSE, FALSE);
8842
8843   /* if the result is rematerializable &
8844      in data space & not a bit variable */
8845   if (AOP_TYPE (result) == AOP_IMMD &&
8846       DCL_TYPE (ptype) == POINTER &&
8847       !IS_BITVAR (retype) &&
8848       !IS_BITVAR (letype))
8849     {
8850       genDataPointerSet (right, result, ic);
8851       return;
8852     }
8853
8854   /* if the value is already in a pointer register
8855      then don't need anything more */
8856   if (!AOP_INPREG (AOP (result)))
8857     {
8858       /* otherwise get a free pointer register */
8859       aop = newAsmop (0);
8860       preg = getFreePtr (ic, &aop, FALSE);
8861       emitcode ("mov", "%s,%s",
8862                 preg->name,
8863                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8864       rname = preg->name;
8865     }
8866   else
8867     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8868
8869   freeAsmop (result, NULL, ic, TRUE);
8870   aopOp (right, ic, FALSE, FALSE);
8871
8872   /* if bitfield then unpack the bits */
8873   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8874     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8875   else
8876     {
8877       /* we have can just get the values */
8878       int size = AOP_SIZE (right);
8879       int offset = 0;
8880
8881       while (size--)
8882         {
8883           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
8884           if (*l == '@')
8885             {
8886               MOVA (l);
8887               emitcode ("mov", "@%s,a", rname);
8888             }
8889           else
8890             emitcode ("mov", "@%s,%s", rname, l);
8891           if (size)
8892             emitcode ("inc", "%s", rname);
8893           offset++;
8894         }
8895     }
8896
8897   /* now some housekeeping stuff */
8898   if (aop)
8899     {
8900       /* we had to allocate for this iCode */
8901       freeAsmop (NULL, aop, ic, TRUE);
8902     }
8903   else
8904     {
8905       /* we did not allocate which means left
8906          already in a pointer register, then
8907          if size > 0 && this could be used again
8908          we have to point it back to where it
8909          belongs */
8910       if (AOP_SIZE (right) > 1 &&
8911           !OP_SYMBOL (result)->remat &&
8912           (OP_SYMBOL (result)->liveTo > ic->seq ||
8913            ic->depth))
8914         {
8915           int size = AOP_SIZE (right) - 1;
8916           while (size--)
8917             emitcode ("dec", "%s", rname);
8918         }
8919     }
8920
8921   /* done */
8922   freeAsmop (right, NULL, ic, TRUE);
8923
8924
8925 }
8926
8927 /*-----------------------------------------------------------------*/
8928 /* genPagedPointerSet - emitcode for Paged pointer put             */
8929 /*-----------------------------------------------------------------*/
8930 static void
8931 genPagedPointerSet (operand * right,
8932                     operand * result,
8933                     iCode * ic)
8934 {
8935   asmop *aop = NULL;
8936   regs *preg = NULL;
8937   char *rname, *l;
8938   sym_link *retype, *letype;
8939
8940   retype = getSpec (operandType (right));
8941   letype = getSpec (operandType (result));
8942
8943   aopOp (result, ic, FALSE, FALSE);
8944
8945   /* if the value is already in a pointer register
8946      then don't need anything more */
8947   if (!AOP_INPREG (AOP (result)))
8948     {
8949       /* otherwise get a free pointer register */
8950       aop = newAsmop (0);
8951       preg = getFreePtr (ic, &aop, FALSE);
8952       emitcode ("mov", "%s,%s",
8953                 preg->name,
8954                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
8955       rname = preg->name;
8956     }
8957   else
8958     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
8959
8960   freeAsmop (result, NULL, ic, TRUE);
8961   aopOp (right, ic, FALSE, FALSE);
8962
8963   /* if bitfield then unpack the bits */
8964   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8965     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8966   else
8967     {
8968       /* we have can just get the values */
8969       int size = AOP_SIZE (right);
8970       int offset = 0;
8971
8972       while (size--)
8973         {
8974           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
8975
8976           MOVA (l);
8977           emitcode ("movx", "@%s,a", rname);
8978
8979           if (size)
8980             emitcode ("inc", "%s", rname);
8981
8982           offset++;
8983         }
8984     }
8985
8986   /* now some housekeeping stuff */
8987   if (aop)
8988     {
8989       /* we had to allocate for this iCode */
8990       freeAsmop (NULL, aop, ic, TRUE);
8991     }
8992   else
8993     {
8994       /* we did not allocate which means left
8995          already in a pointer register, then
8996          if size > 0 && this could be used again
8997          we have to point it back to where it
8998          belongs */
8999       if (AOP_SIZE (right) > 1 &&
9000           !OP_SYMBOL (result)->remat &&
9001           (OP_SYMBOL (result)->liveTo > ic->seq ||
9002            ic->depth))
9003         {
9004           int size = AOP_SIZE (right) - 1;
9005           while (size--)
9006             emitcode ("dec", "%s", rname);
9007         }
9008     }
9009
9010   /* done */
9011   freeAsmop (right, NULL, ic, TRUE);
9012
9013
9014 }
9015
9016 /*-----------------------------------------------------------------*/
9017 /* genFarPointerSet - set value from far space                     */
9018 /*-----------------------------------------------------------------*/
9019 static void
9020 genFarPointerSet (operand * right,
9021                   operand * result, iCode * ic)
9022 {
9023   int size, offset;
9024   sym_link *retype = getSpec (operandType (right));
9025   sym_link *letype = getSpec (operandType (result));
9026
9027   aopOp (result, ic, FALSE, FALSE);
9028
9029   /* if the operand is already in dptr
9030      then we do nothing else we move the value to dptr */
9031   if (AOP_TYPE (result) != AOP_STR)
9032     {
9033       /* if this is remateriazable */
9034       if (AOP_TYPE (result) == AOP_IMMD)
9035         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9036       else
9037         {
9038           /* we need to get it byte by byte */
9039           _startLazyDPSEvaluation ();
9040           if (AOP_TYPE (result) != AOP_DPTR)
9041             {
9042               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9043               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9044               if (options.model == MODEL_FLAT24)
9045                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9046             }
9047           else
9048             {
9049               /* We need to generate a load to DPTR indirect through DPTR. */
9050               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9051                 );
9052               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9053               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9054               if (options.model == MODEL_FLAT24)
9055                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9056               emitcode ("pop", "dph");
9057               emitcode ("pop", "dpl");
9058             }
9059           _endLazyDPSEvaluation ();
9060         }
9061     }
9062   /* so dptr know contains the address */
9063   freeAsmop (result, NULL, ic, TRUE);
9064   aopOp (right, ic, FALSE, TRUE);
9065
9066   /* if bit then unpack */
9067   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9068     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9069   else
9070     {
9071       size = AOP_SIZE (right);
9072       offset = 0;
9073
9074       _startLazyDPSEvaluation ();
9075       while (size--)
9076         {
9077           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9078           MOVA (l);
9079
9080           genSetDPTR (0);
9081           _flushLazyDPS ();
9082
9083           emitcode ("movx", "@dptr,a");
9084           if (size)
9085             emitcode ("inc", "dptr");
9086         }
9087       _endLazyDPSEvaluation ();
9088     }
9089
9090   freeAsmop (right, NULL, ic, TRUE);
9091 }
9092
9093 /*-----------------------------------------------------------------*/
9094 /* genGenPointerSet - set value from generic pointer space         */
9095 /*-----------------------------------------------------------------*/
9096 static void
9097 genGenPointerSet (operand * right,
9098                   operand * result, iCode * ic)
9099 {
9100   int size, offset;
9101   sym_link *retype = getSpec (operandType (right));
9102   sym_link *letype = getSpec (operandType (result));
9103
9104   aopOp (result, ic, FALSE, TRUE);
9105
9106   /* if the operand is already in dptr
9107      then we do nothing else we move the value to dptr */
9108   if (AOP_TYPE (result) != AOP_STR)
9109     {
9110       _startLazyDPSEvaluation ();
9111       /* if this is remateriazable */
9112       if (AOP_TYPE (result) == AOP_IMMD)
9113         {
9114           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9115           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9116         }
9117       else
9118         {                       /* we need to get it byte by byte */
9119           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9120           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9121           if (options.model == MODEL_FLAT24) {
9122             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9123             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9124           } else {
9125             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9126           }
9127         }
9128       _endLazyDPSEvaluation ();
9129     }
9130   /* so dptr know contains the address */
9131   freeAsmop (result, NULL, ic, TRUE);
9132   aopOp (right, ic, FALSE, TRUE);
9133
9134   /* if bit then unpack */
9135   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9136     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9137   else
9138     {
9139       size = AOP_SIZE (right);
9140       offset = 0;
9141
9142       _startLazyDPSEvaluation ();
9143       while (size--)
9144         {
9145           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9146           MOVA (l);
9147
9148           genSetDPTR (0);
9149           _flushLazyDPS ();
9150
9151           emitcode ("lcall", "__gptrput");
9152           if (size)
9153             emitcode ("inc", "dptr");
9154         }
9155       _endLazyDPSEvaluation ();
9156     }
9157
9158   freeAsmop (right, NULL, ic, TRUE);
9159 }
9160
9161 /*-----------------------------------------------------------------*/
9162 /* genPointerSet - stores the value into a pointer location        */
9163 /*-----------------------------------------------------------------*/
9164 static void
9165 genPointerSet (iCode * ic)
9166 {
9167   operand *right, *result;
9168   sym_link *type, *etype;
9169   int p_type;
9170
9171   D (emitcode (";", "genPointerSet ");
9172     );
9173
9174   right = IC_RIGHT (ic);
9175   result = IC_RESULT (ic);
9176
9177   /* depending on the type of pointer we need to
9178      move it to the correct pointer register */
9179   type = operandType (result);
9180   etype = getSpec (type);
9181   /* if left is of type of pointer then it is simple */
9182   if (IS_PTR (type) && !IS_FUNC (type->next))
9183     {
9184       p_type = DCL_TYPE (type);
9185     }
9186   else
9187     {
9188       /* we have to go by the storage class */
9189       p_type = PTR_TYPE (SPEC_OCLS (etype));
9190     }
9191
9192   /* now that we have the pointer type we assign
9193      the pointer values */
9194   switch (p_type)
9195     {
9196
9197     case POINTER:
9198     case IPOINTER:
9199       genNearPointerSet (right, result, ic);
9200       break;
9201
9202     case PPOINTER:
9203       genPagedPointerSet (right, result, ic);
9204       break;
9205
9206     case FPOINTER:
9207       genFarPointerSet (right, result, ic);
9208       break;
9209
9210     case GPOINTER:
9211       genGenPointerSet (right, result, ic);
9212       break;
9213     }
9214
9215 }
9216
9217 /*-----------------------------------------------------------------*/
9218 /* genIfx - generate code for Ifx statement                        */
9219 /*-----------------------------------------------------------------*/
9220 static void
9221 genIfx (iCode * ic, iCode * popIc)
9222 {
9223   operand *cond = IC_COND (ic);
9224   int isbit = 0;
9225
9226   D (emitcode (";", "genIfx "););
9227
9228   aopOp (cond, ic, FALSE, FALSE);
9229
9230   /* get the value into acc */
9231   if (AOP_TYPE (cond) != AOP_CRY)
9232     toBoolean (cond);
9233   else
9234     isbit = 1;
9235   /* the result is now in the accumulator */
9236   freeAsmop (cond, NULL, ic, TRUE);
9237
9238   /* if there was something to be popped then do it */
9239   if (popIc)
9240     genIpop (popIc);
9241
9242   /* if the condition is  a bit variable */
9243   if (isbit && IS_ITEMP (cond) &&
9244       SPIL_LOC (cond))
9245     genIfxJump (ic, SPIL_LOC (cond)->rname);
9246   else if (isbit && !IS_ITEMP (cond))
9247     genIfxJump (ic, OP_SYMBOL (cond)->rname);
9248   else
9249     genIfxJump (ic, "a");
9250
9251   ic->generated = 1;
9252 }
9253
9254 /*-----------------------------------------------------------------*/
9255 /* genAddrOf - generates code for address of                       */
9256 /*-----------------------------------------------------------------*/
9257 static void
9258 genAddrOf (iCode * ic)
9259 {
9260   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9261   int size, offset;
9262
9263   D (emitcode (";", "genAddrOf ");
9264     );
9265
9266   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9267
9268   /* if the operand is on the stack then we
9269      need to get the stack offset of this
9270      variable */
9271   if (sym->onStack)
9272     {
9273       /* if it has an offset then we need to compute
9274          it */
9275       if (sym->stack)
9276         {
9277           emitcode ("mov", "a,_bp");
9278           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9279           aopPut (AOP (IC_RESULT (ic)), "a", 0);
9280         }
9281       else
9282         {
9283           /* we can just move _bp */
9284           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9285         }
9286       /* fill the result with zero */
9287       size = AOP_SIZE (IC_RESULT (ic)) - 1;
9288
9289
9290       if (options.stack10bit && size < (FPTRSIZE - 1))
9291         {
9292           fprintf (stderr,
9293                    "*** warning: pointer to stack var truncated.\n");
9294         }
9295
9296       offset = 1;
9297       while (size--)
9298         {
9299           /* Yuck! */
9300           if (options.stack10bit && offset == 2)
9301             {
9302               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9303             }
9304           else
9305             {
9306               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9307             }
9308         }
9309
9310       goto release;
9311     }
9312
9313   /* object not on stack then we need the name */
9314   size = AOP_SIZE (IC_RESULT (ic));
9315   offset = 0;
9316
9317   while (size--)
9318     {
9319       char s[SDCC_NAME_MAX];
9320       if (offset)
9321         sprintf (s, "#(%s >> %d)",
9322                  sym->rname,
9323                  offset * 8);
9324       else
9325         sprintf (s, "#%s", sym->rname);
9326       aopPut (AOP (IC_RESULT (ic)), s, offset++);
9327     }
9328
9329 release:
9330   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9331
9332 }
9333
9334 /*-----------------------------------------------------------------*/
9335 /* genArrayInit - generates code for address of                       */
9336 /*-----------------------------------------------------------------*/
9337 static void
9338 genArrayInit (iCode * ic)
9339 {
9340     literalList *iLoop;
9341     int         ix, count;
9342     int         elementSize = 0, eIndex;
9343     unsigned    val, lastVal;
9344     sym_link    *type;
9345     operand     *left=IC_LEFT(ic);
9346     
9347     D (emitcode (";", "genArrayInit "););
9348
9349     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9350     
9351     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9352     {
9353         // Load immediate value into DPTR.
9354         emitcode("mov", "dptr, %s",
9355              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9356     }
9357     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9358     {
9359 #if 0
9360       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9361               "Unexpected operand to genArrayInit.\n");
9362       exit(1);
9363 #else
9364       // a regression because of SDCCcse.c:1.52
9365       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9366       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9367       if (options.model == MODEL_FLAT24)
9368         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9369 #endif
9370     }
9371     
9372     type = operandType(IC_LEFT(ic));
9373     
9374     if (type && type->next)
9375     {
9376         elementSize = getSize(type->next);
9377     }
9378     else
9379     {
9380         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9381                                 "can't determine element size in genArrayInit.\n");
9382         exit(1);
9383     }
9384     
9385     iLoop = IC_ARRAYILIST(ic);
9386     lastVal = 0xffff;
9387     
9388     while (iLoop)
9389     {
9390         bool firstpass = TRUE;
9391         
9392         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
9393                  iLoop->count, (int)iLoop->literalValue, elementSize);
9394         
9395         ix = iLoop->count;
9396         
9397         while (ix)
9398         {
9399             symbol *tlbl = NULL;
9400             
9401             count = ix > 256 ? 256 : ix;
9402             
9403             if (count > 1)
9404             {
9405                 tlbl = newiTempLabel (NULL);
9406                 if (firstpass || (count & 0xff))
9407                 {
9408                     emitcode("mov", "b, #0x%x", count & 0xff);
9409                 }
9410                 
9411                 emitcode ("", "%05d$:", tlbl->key + 100);
9412             }
9413             
9414             firstpass = FALSE;
9415                 
9416             for (eIndex = 0; eIndex < elementSize; eIndex++)
9417             {
9418                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9419                 if (val != lastVal)
9420                 {
9421                     emitcode("mov", "a, #0x%x", val);
9422                     lastVal = val;
9423                 }
9424                 
9425                 emitcode("movx", "@dptr, a");
9426                 emitcode("inc", "dptr");
9427             }
9428             
9429             if (count > 1)
9430             {
9431                 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9432             }
9433             
9434             ix -= count;
9435         }
9436         
9437         iLoop = iLoop->next;
9438     }
9439     
9440     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9441 }
9442
9443 /*-----------------------------------------------------------------*/
9444 /* genFarFarAssign - assignment when both are in far space         */
9445 /*-----------------------------------------------------------------*/
9446 static void
9447 genFarFarAssign (operand * result, operand * right, iCode * ic)
9448 {
9449   int size = AOP_SIZE (right);
9450   int offset = 0;
9451   symbol *rSym = NULL;
9452
9453   if (size == 1)
9454   {
9455       /* quick & easy case. */
9456       D(emitcode(";","genFarFarAssign (1 byte case)"););      
9457       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9458       freeAsmop (right, NULL, ic, FALSE);
9459       /* now assign DPTR to result */
9460       _G.accInUse++;
9461       aopOp(result, ic, FALSE, FALSE);
9462       _G.accInUse--;
9463       aopPut(AOP(result), "a", 0);
9464       freeAsmop(result, NULL, ic, FALSE);
9465       return;
9466   }
9467   
9468   /* See if we've got an underlying symbol to abuse. */
9469   if (IS_SYMOP(result) && OP_SYMBOL(result))
9470   {
9471       if (IS_TRUE_SYMOP(result))
9472       {
9473           rSym = OP_SYMBOL(result);
9474       }
9475       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9476       {
9477           rSym = OP_SYMBOL(result)->usl.spillLoc;
9478       }
9479   }
9480              
9481   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9482   {
9483       /* We can use the '390 auto-toggle feature to good effect here. */
9484       
9485       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9486       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
9487       emitcode ("mov", "dptr,#%s", rSym->rname); 
9488       /* DP2 = result, DP1 = right, DP1 is current. */
9489       while (size)
9490       {
9491           emitcode("movx", "a,@dptr");
9492           emitcode("movx", "@dptr,a");
9493           if (--size)
9494           {
9495                emitcode("inc", "dptr");
9496                emitcode("inc", "dptr");
9497           }
9498       }
9499       emitcode("mov", "dps, #0");
9500       freeAsmop (right, NULL, ic, FALSE);
9501 #if 0
9502 some alternative code for processors without auto-toggle
9503 no time to test now, so later well put in...kpb
9504         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9505         emitcode("mov", "dps, #0x01");  /* Select DPTR2. */
9506         emitcode ("mov", "dptr,#%s", rSym->rname); 
9507         /* DP2 = result, DP1 = right, DP1 is current. */
9508         while (size)
9509         {
9510           --size;
9511           emitcode("movx", "a,@dptr");
9512           if (size)
9513             emitcode("inc", "dptr");
9514           emitcode("inc", "dps");
9515           emitcode("movx", "@dptr,a");
9516           if (size)
9517             emitcode("inc", "dptr");
9518           emitcode("inc", "dps");
9519         }
9520         emitcode("mov", "dps, #0");
9521         freeAsmop (right, NULL, ic, FALSE);
9522 #endif
9523   }
9524   else
9525   {
9526       D (emitcode (";", "genFarFarAssign"););
9527       aopOp (result, ic, TRUE, TRUE);
9528
9529       _startLazyDPSEvaluation ();
9530       
9531       while (size--)
9532         {
9533           aopPut (AOP (result),
9534                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9535           offset++;
9536         }
9537       _endLazyDPSEvaluation ();
9538       freeAsmop (result, NULL, ic, FALSE);
9539       freeAsmop (right, NULL, ic, FALSE);
9540   }
9541 }
9542
9543 /*-----------------------------------------------------------------*/
9544 /* genAssign - generate code for assignment                        */
9545 /*-----------------------------------------------------------------*/
9546 static void
9547 genAssign (iCode * ic)
9548 {
9549   operand *result, *right;
9550   int size, offset;
9551   unsigned long lit = 0L;
9552
9553   D (emitcode (";", "genAssign ");
9554     );
9555
9556   result = IC_RESULT (ic);
9557   right = IC_RIGHT (ic);
9558
9559   /* if they are the same */
9560   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9561     return;
9562
9563   aopOp (right, ic, FALSE, FALSE);
9564
9565   emitcode (";", "genAssign: resultIsFar = %s",
9566             isOperandInFarSpace (result) ?
9567             "TRUE" : "FALSE");
9568
9569   /* special case both in far space */
9570   if ((AOP_TYPE (right) == AOP_DPTR ||
9571        AOP_TYPE (right) == AOP_DPTR2) &&
9572   /* IS_TRUE_SYMOP(result)       && */
9573       isOperandInFarSpace (result))
9574     {
9575       genFarFarAssign (result, right, ic);
9576       return;
9577     }
9578
9579   aopOp (result, ic, TRUE, FALSE);
9580
9581   /* if they are the same registers */
9582   if (sameRegs (AOP (right), AOP (result)))
9583     goto release;
9584
9585   /* if the result is a bit */
9586   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9587     {
9588       /* if the right size is a literal then
9589          we know what the value is */
9590       if (AOP_TYPE (right) == AOP_LIT)
9591         {
9592           if (((int) operandLitValue (right)))
9593             aopPut (AOP (result), one, 0);
9594           else
9595             aopPut (AOP (result), zero, 0);
9596           goto release;
9597         }
9598
9599       /* the right is also a bit variable */
9600       if (AOP_TYPE (right) == AOP_CRY)
9601         {
9602           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9603           aopPut (AOP (result), "c", 0);
9604           goto release;
9605         }
9606
9607       /* we need to or */
9608       toBoolean (right);
9609       aopPut (AOP (result), "a", 0);
9610       goto release;
9611     }
9612
9613   /* bit variables done */
9614   /* general case */
9615   size = AOP_SIZE (result);
9616   offset = 0;
9617   if (AOP_TYPE (right) == AOP_LIT)
9618     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9619
9620   if ((size > 1) &&
9621       (AOP_TYPE (result) != AOP_REG) &&
9622       (AOP_TYPE (right) == AOP_LIT) &&
9623       !IS_FLOAT (operandType (right)))
9624     {
9625       _startLazyDPSEvaluation ();
9626       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9627         {
9628           aopPut (AOP (result),
9629                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9630                   offset);
9631           offset++;
9632           size--;
9633         }
9634       /* And now fill the rest with zeros. */
9635       if (size)
9636         {
9637           emitcode ("clr", "a");
9638         }
9639       while (size--)
9640         {
9641           aopPut (AOP (result), "a", offset++);
9642         }
9643       _endLazyDPSEvaluation ();
9644     }
9645   else
9646     {
9647       _startLazyDPSEvaluation ();
9648       while (size--)
9649         {
9650           aopPut (AOP (result),
9651                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9652                   offset);
9653           offset++;
9654         }
9655       _endLazyDPSEvaluation ();
9656     }
9657
9658 release:
9659   freeAsmop (right, NULL, ic, FALSE);
9660   freeAsmop (result, NULL, ic, TRUE);
9661 }
9662
9663 /*-----------------------------------------------------------------*/
9664 /* genJumpTab - generates code for jump table                      */
9665 /*-----------------------------------------------------------------*/
9666 static void
9667 genJumpTab (iCode * ic)
9668 {
9669   symbol *jtab;
9670   char *l;
9671
9672   D (emitcode (";", "genJumpTab ");
9673     );
9674
9675   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
9676   /* get the condition into accumulator */
9677   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
9678   MOVA (l);
9679   /* multiply by four! */
9680   emitcode ("add", "a,acc");
9681   emitcode ("add", "a,acc");
9682   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9683
9684   jtab = newiTempLabel (NULL);
9685   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9686   emitcode ("jmp", "@a+dptr");
9687   emitcode ("", "%05d$:", jtab->key + 100);
9688   /* now generate the jump labels */
9689   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9690        jtab = setNextItem (IC_JTLABELS (ic)))
9691     emitcode ("ljmp", "%05d$", jtab->key + 100);
9692
9693 }
9694
9695 /*-----------------------------------------------------------------*/
9696 /* genCast - gen code for casting                                  */
9697 /*-----------------------------------------------------------------*/
9698 static void
9699 genCast (iCode * ic)
9700 {
9701   operand *result = IC_RESULT (ic);
9702   sym_link *ctype = operandType (IC_LEFT (ic));
9703   sym_link *rtype = operandType (IC_RIGHT (ic));
9704   operand *right = IC_RIGHT (ic);
9705   int size, offset;
9706
9707   D (emitcode (";", "genCast ");
9708     );
9709
9710   /* if they are equivalent then do nothing */
9711   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9712     return;
9713
9714   aopOp (right, ic, FALSE, FALSE);
9715   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
9716
9717   /* if the result is a bit */
9718   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9719   if (IS_BITVAR(OP_SYMBOL(result)->type))
9720     {
9721       /* if the right size is a literal then
9722          we know what the value is */
9723       if (AOP_TYPE (right) == AOP_LIT)
9724         {
9725           if (((int) operandLitValue (right)))
9726             aopPut (AOP (result), one, 0);
9727           else
9728             aopPut (AOP (result), zero, 0);
9729
9730           goto release;
9731         }
9732
9733       /* the right is also a bit variable */
9734       if (AOP_TYPE (right) == AOP_CRY)
9735         {
9736           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9737           aopPut (AOP (result), "c", 0);
9738           goto release;
9739         }
9740
9741       /* we need to or */
9742       toBoolean (right);
9743       aopPut (AOP (result), "a", 0);
9744       goto release;
9745     }
9746
9747   /* if they are the same size : or less */
9748   if (AOP_SIZE (result) <= AOP_SIZE (right))
9749     {
9750
9751       /* if they are in the same place */
9752       if (sameRegs (AOP (right), AOP (result)))
9753         goto release;
9754
9755       /* if they in different places then copy */
9756       size = AOP_SIZE (result);
9757       offset = 0;
9758       _startLazyDPSEvaluation ();
9759       while (size--)
9760         {
9761           aopPut (AOP (result),
9762                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9763                   offset);
9764           offset++;
9765         }
9766       _endLazyDPSEvaluation ();
9767       goto release;
9768     }
9769
9770
9771   /* if the result is of type pointer */
9772   if (IS_PTR (ctype))
9773     {
9774
9775       int p_type;
9776       sym_link *type = operandType (right);
9777
9778       /* pointer to generic pointer */
9779       if (IS_GENPTR (ctype))
9780         {
9781           char *l = zero;
9782
9783           if (IS_PTR (type))
9784             {
9785               p_type = DCL_TYPE (type);
9786             }
9787           else
9788             {
9789 #if OLD_CAST_BEHAVIOR
9790               /* KV: we are converting a non-pointer type to
9791                * a generic pointer. This (ifdef'd out) code
9792                * says that the resulting generic pointer
9793                * should have the same class as the storage
9794                * location of the non-pointer variable.
9795                *
9796                * For example, converting an int (which happens
9797                * to be stored in DATA space) to a pointer results
9798                * in a DATA generic pointer; if the original int
9799                * in XDATA space, so will be the resulting pointer.
9800                *
9801                * I don't like that behavior, and thus this change:
9802                * all such conversions will be forced to XDATA and
9803                * throw a warning. If you want some non-XDATA
9804                * type, or you want to suppress the warning, you
9805                * must go through an intermediate cast, like so:
9806                *
9807                * char _generic *gp = (char _xdata *)(intVar);
9808                */
9809               sym_link *etype = getSpec (type);
9810
9811               /* we have to go by the storage class */
9812               if (SPEC_OCLS (etype) != generic)
9813                 {
9814                   p_type = PTR_TYPE (SPEC_OCLS (etype));
9815                 }
9816               else
9817 #endif
9818                 {
9819                   /* Converting unknown class (i.e. register variable)
9820                    * to generic pointer. This is not good, but
9821                    * we'll make a guess (and throw a warning).
9822                    */
9823                   p_type = FPOINTER;
9824                   werror (W_INT_TO_GEN_PTR_CAST);
9825                 }
9826             }
9827
9828           /* the first two bytes are known */
9829           size = GPTRSIZE - 1;
9830           offset = 0;
9831           _startLazyDPSEvaluation ();
9832           while (size--)
9833             {
9834               aopPut (AOP (result),
9835                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9836                       offset);
9837               offset++;
9838             }
9839           _endLazyDPSEvaluation ();
9840
9841           /* the last byte depending on type */
9842           switch (p_type)
9843             {
9844             case IPOINTER:
9845             case POINTER:
9846               l = zero;
9847               break;
9848             case FPOINTER:
9849               l = one;
9850               break;
9851             case CPOINTER:
9852               l = "#0x02";
9853               break;
9854             case PPOINTER:
9855               l = "#0x03";
9856               break;
9857
9858             default:
9859               /* this should never happen */
9860               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9861                       "got unknown pointer type");
9862               exit (1);
9863             }
9864           aopPut (AOP (result), l, GPTRSIZE - 1);
9865           goto release;
9866         }
9867
9868       /* just copy the pointers */
9869       size = AOP_SIZE (result);
9870       offset = 0;
9871       _startLazyDPSEvaluation ();
9872       while (size--)
9873         {
9874           aopPut (AOP (result),
9875                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9876                   offset);
9877           offset++;
9878         }
9879       _endLazyDPSEvaluation ();
9880       goto release;
9881     }
9882
9883   /* so we now know that the size of destination is greater
9884      than the size of the source */
9885   /* we move to result for the size of source */
9886   size = AOP_SIZE (right);
9887   offset = 0;
9888   _startLazyDPSEvaluation ();
9889   while (size--)
9890     {
9891       aopPut (AOP (result),
9892               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9893               offset);
9894       offset++;
9895     }
9896   _endLazyDPSEvaluation ();
9897
9898   /* now depending on the sign of the source && destination */
9899   size = AOP_SIZE (result) - AOP_SIZE (right);
9900   /* if unsigned or not an integral type */
9901   /* also, if the source is a bit, we don't need to sign extend, because
9902    * it can't possibly have set the sign bit.
9903    */
9904   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
9905     {
9906       while (size--)
9907         {
9908           aopPut (AOP (result), zero, offset++);
9909         }
9910     }
9911   else
9912     {
9913       /* we need to extend the sign :{ */
9914       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
9915                         FALSE, FALSE, TRUE);
9916       MOVA (l);
9917       emitcode ("rlc", "a");
9918       emitcode ("subb", "a,acc");
9919       while (size--)
9920         aopPut (AOP (result), "a", offset++);
9921     }
9922
9923   /* we are done hurray !!!! */
9924
9925 release:
9926   freeAsmop (right, NULL, ic, TRUE);
9927   freeAsmop (result, NULL, ic, TRUE);
9928
9929 }
9930
9931 /*-----------------------------------------------------------------*/
9932 /* genDjnz - generate decrement & jump if not zero instrucion      */
9933 /*-----------------------------------------------------------------*/
9934 static int
9935 genDjnz (iCode * ic, iCode * ifx)
9936 {
9937   symbol *lbl, *lbl1;
9938   if (!ifx)
9939     return 0;
9940
9941   /* if the if condition has a false label
9942      then we cannot save */
9943   if (IC_FALSE (ifx))
9944     return 0;
9945
9946   /* if the minus is not of the form
9947      a = a - 1 */
9948   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9949       !IS_OP_LITERAL (IC_RIGHT (ic)))
9950     return 0;
9951
9952   if (operandLitValue (IC_RIGHT (ic)) != 1)
9953     return 0;
9954
9955   /* if the size of this greater than one then no
9956      saving */
9957   if (getSize (operandType (IC_RESULT (ic))) > 1)
9958     return 0;
9959
9960   /* otherwise we can save BIG */
9961   D(emitcode(";", "genDjnz"););
9962
9963   lbl = newiTempLabel (NULL);
9964   lbl1 = newiTempLabel (NULL);
9965
9966   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9967
9968   if (AOP_NEEDSACC(IC_RESULT(ic)))
9969   {
9970       /* If the result is accessed indirectly via
9971        * the accumulator, we must explicitly write
9972        * it back after the decrement.
9973        */
9974       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
9975       
9976       if (strcmp(rByte, "a"))
9977       {
9978            /* Something is hopelessly wrong */
9979            fprintf(stderr, "*** warning: internal error at %s:%d\n",
9980                    __FILE__, __LINE__);
9981            /* We can just give up; the generated code will be inefficient,
9982             * but what the hey.
9983             */
9984            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9985            return 0;
9986       }
9987       emitcode ("dec", "%s", rByte);
9988       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
9989       emitcode ("jnz", "%05d$", lbl->key + 100);
9990   }
9991   else if (IS_AOP_PREG (IC_RESULT (ic)))
9992     {
9993       emitcode ("dec", "%s",
9994                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9995       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
9996       emitcode ("jnz", "%05d$", lbl->key + 100);
9997     }
9998   else
9999     {
10000       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10001                 lbl->key + 100);
10002     }
10003   emitcode ("sjmp", "%05d$", lbl1->key + 100);
10004   emitcode ("", "%05d$:", lbl->key + 100);
10005   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10006   emitcode ("", "%05d$:", lbl1->key + 100);
10007
10008   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10009   ifx->generated = 1;
10010   return 1;
10011 }
10012
10013 /*-----------------------------------------------------------------*/
10014 /* genReceive - generate code for a receive iCode                  */
10015 /*-----------------------------------------------------------------*/
10016 static void
10017 genReceive (iCode * ic)
10018 {
10019
10020   D (emitcode (";", "genReceive ");
10021     );
10022
10023   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10024       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10025        IS_TRUE_SYMOP (IC_RESULT (ic))))
10026     {
10027       int size = getSize (operandType (IC_RESULT (ic)));
10028       int offset = fReturnSizeDS390 - size;
10029       while (size--)
10030         {
10031           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10032                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10033           offset++;
10034         }
10035       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10036       size = AOP_SIZE (IC_RESULT (ic));
10037       offset = 0;
10038       while (size--)
10039         {
10040           emitcode ("pop", "acc");
10041           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10042         }
10043
10044     }
10045   else
10046     {
10047       _G.accInUse++;
10048       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10049       _G.accInUse--;
10050       assignResultValue (IC_RESULT (ic));
10051     }
10052
10053   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10054 }
10055
10056 /*-----------------------------------------------------------------*/
10057 /* gen390Code - generate code for Dallas 390 based controllers     */
10058 /*-----------------------------------------------------------------*/
10059 void
10060 gen390Code (iCode * lic)
10061 {
10062   iCode *ic;
10063   int cln = 0;
10064
10065   lineHead = lineCurr = NULL;
10066
10067   if (options.model == MODEL_FLAT24) {
10068     fReturnSizeDS390 = 5;
10069     fReturn = fReturn24;
10070   } else {
10071     fReturnSizeDS390 = 4;
10072     fReturn = fReturn16;
10073     options.stack10bit=0;
10074   }
10075 #if 0
10076   //REMOVE ME!!!
10077   /* print the allocation information */
10078   if (allocInfo)
10079     printAllocInfo (currFunc, codeOutFile);
10080 #endif
10081   /* if debug information required */
10082   if (options.debug && currFunc)
10083     {
10084       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10085       _G.debugLine = 1;
10086       if (IS_STATIC (currFunc->etype))
10087         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10088       else
10089         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10090       _G.debugLine = 0;
10091     }
10092   /* stack pointer name */
10093   if (options.useXstack)
10094     spname = "_spx";
10095   else
10096     spname = "sp";
10097
10098
10099   for (ic = lic; ic; ic = ic->next)
10100     {
10101
10102       if (cln != ic->lineno)
10103         {
10104           if (options.debug)
10105             {
10106               _G.debugLine = 1;
10107               emitcode ("", "C$%s$%d$%d$%d ==.",
10108                         FileBaseName (ic->filename), ic->lineno,
10109                         ic->level, ic->block);
10110               _G.debugLine = 0;
10111             }
10112           emitcode (";", "%s %d", ic->filename, ic->lineno);
10113           cln = ic->lineno;
10114         }
10115       /* if the result is marked as
10116          spilt and rematerializable or code for
10117          this has already been generated then
10118          do nothing */
10119       if (resultRemat (ic) || ic->generated)
10120         continue;
10121
10122       /* depending on the operation */
10123       switch (ic->op)
10124         {
10125         case '!':
10126           genNot (ic);
10127           break;
10128
10129         case '~':
10130           genCpl (ic);
10131           break;
10132
10133         case UNARYMINUS:
10134           genUminus (ic);
10135           break;
10136
10137         case IPUSH:
10138           genIpush (ic);
10139           break;
10140
10141         case IPOP:
10142           /* IPOP happens only when trying to restore a
10143              spilt live range, if there is an ifx statement
10144              following this pop then the if statement might
10145              be using some of the registers being popped which
10146              would destory the contents of the register so
10147              we need to check for this condition and handle it */
10148           if (ic->next &&
10149               ic->next->op == IFX &&
10150               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10151             genIfx (ic->next, ic);
10152           else
10153             genIpop (ic);
10154           break;
10155
10156         case CALL:
10157           genCall (ic);
10158           break;
10159
10160         case PCALL:
10161           genPcall (ic);
10162           break;
10163
10164         case FUNCTION:
10165           genFunction (ic);
10166           break;
10167
10168         case ENDFUNCTION:
10169           genEndFunction (ic);
10170           break;
10171
10172         case RETURN:
10173           genRet (ic);
10174           break;
10175
10176         case LABEL:
10177           genLabel (ic);
10178           break;
10179
10180         case GOTO:
10181           genGoto (ic);
10182           break;
10183
10184         case '+':
10185           genPlus (ic);
10186           break;
10187
10188         case '-':
10189           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10190             genMinus (ic);
10191           break;
10192
10193         case '*':
10194           genMult (ic);
10195           break;
10196
10197         case '/':
10198           genDiv (ic);
10199           break;
10200
10201         case '%':
10202           genMod (ic);
10203           break;
10204
10205         case '>':
10206           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10207           break;
10208
10209         case '<':
10210           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10211           break;
10212
10213         case LE_OP:
10214         case GE_OP:
10215         case NE_OP:
10216
10217           /* note these two are xlated by algebraic equivalence
10218              during parsing SDCC.y */
10219           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10220                   "got '>=' or '<=' shouldn't have come here");
10221           break;
10222
10223         case EQ_OP:
10224           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10225           break;
10226
10227         case AND_OP:
10228           genAndOp (ic);
10229           break;
10230
10231         case OR_OP:
10232           genOrOp (ic);
10233           break;
10234
10235         case '^':
10236           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10237           break;
10238
10239         case '|':
10240           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10241           break;
10242
10243         case BITWISEAND:
10244           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10245           break;
10246
10247         case INLINEASM:
10248           genInline (ic);
10249           break;
10250
10251         case RRC:
10252           genRRC (ic);
10253           break;
10254
10255         case RLC:
10256           genRLC (ic);
10257           break;
10258
10259         case GETHBIT:
10260           genGetHbit (ic);
10261           break;
10262
10263         case LEFT_OP:
10264           genLeftShift (ic);
10265           break;
10266
10267         case RIGHT_OP:
10268           genRightShift (ic);
10269           break;
10270
10271         case GET_VALUE_AT_ADDRESS:
10272           genPointerGet (ic);
10273           break;
10274
10275         case '=':
10276           if (POINTER_SET (ic))
10277             genPointerSet (ic);
10278           else
10279             genAssign (ic);
10280           break;
10281
10282         case IFX:
10283           genIfx (ic, NULL);
10284           break;
10285
10286         case ADDRESS_OF:
10287           genAddrOf (ic);
10288           break;
10289
10290         case JUMPTABLE:
10291           genJumpTab (ic);
10292           break;
10293
10294         case CAST:
10295           genCast (ic);
10296           break;
10297
10298         case RECEIVE:
10299           genReceive (ic);
10300           break;
10301
10302         case SEND:
10303           addSet (&_G.sendSet, ic);
10304           break;
10305
10306         case ARRAYINIT:
10307             genArrayInit(ic);
10308             break;
10309             
10310         default:
10311           ic = ic;
10312         }
10313     }
10314
10315
10316   /* now we are ready to call the
10317      peep hole optimizer */
10318   if (!options.nopeep)
10319     peepHole (&lineHead);
10320
10321   /* now do the actual printing */
10322   printLine (lineHead, codeOutFile);
10323   return;
10324 }