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