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