Added support for DS390 Arithmetic Accelerator
[fw/sdcc] / src / ds390 / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for DS80C390
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7
8   This program is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by the
10   Free Software Foundation; either version 2, or (at your option) any
11   later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22   In other words, you are welcome to use, share and improve this program.
23   You are forbidden to forbid anyone else to use, share and improve
24   what you give them.   Help stamp out software-hoarding!
25 -------------------------------------------------------------------------*/
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <ctype.h>
31
32 #include <common.h>
33 #include "ralloc.h"
34 #include "gen.h"
35 #include "SDCCglobl.h"
36 #include "newalloc.h"
37
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
40 #else
41 #ifdef HAVE_MACHINE_ENDIAN_H
42 #include <machine/endian.h>
43 #else
44 #ifdef HAVE_ENDIAN_H
45 #include <endian.h>
46 #else
47 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
48 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
49 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
50 #endif
51 #endif
52 #endif
53 #endif
54
55 #define BETTER_LITERAL_SHIFT
56
57 char *aopLiteral (value * val, int offset);
58
59 /* this is the down and dirty file with all kinds of
60    kludgy & hacky stuff. This is what it is all about
61    CODE GENERATION for a specific MCU . some of the
62    routines may be reusable, will have to see */
63
64 static char *zero = "#0x00";
65 static char *one = "#0x01";
66 static char *spname;
67
68 #define D(x) x
69
70 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
71 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
72
73 unsigned fReturnSizeDS390 = 5;  /* shared with ralloc.c */
74 static char *fReturn24[] =
75 {"dpl", "dph", "dpx", "b", "a"};
76 static char *fReturn16[] =
77 {"dpl", "dph", "b", "a"};
78 static char **fReturn = fReturn24;
79 static char *accUse[] =
80 {"a", "b"};
81
82 static short rbank = -1;
83
84 static struct
85   {
86     short r0Pushed;
87     short r1Pushed;
88     short accInUse;
89     short inLine;
90     short debugLine;
91     short nRegsSaved;
92     set *sendSet;
93   }
94 _G;
95
96 static void saveRBank (int, iCode *, bool);
97
98 #define RESULTONSTACK(x) \
99                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
100                          IC_RESULT(x)->aop->type == AOP_STK )
101
102 /* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
103 #define MOVA(x) { char *_mova_tmp = strdup(x); \
104                  if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
105                  { \
106                     emitcode("mov","a,%s",_mova_tmp); \
107                  } \
108                  free(_mova_tmp); \
109                 }
110 #define CLRC    emitcode("clr","c")
111 #define SETC    emitcode("setb","c")
112
113 // A scratch register which will be used to hold
114 // result bytes from operands in far space via DPTR2.
115 #define DP2_RESULT_REG  "ap"
116
117 static lineNode *lineHead = NULL;
118 static lineNode *lineCurr = NULL;
119
120 static unsigned char SLMask[] =
121 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
122  0xE0, 0xC0, 0x80, 0x00};
123 static unsigned char SRMask[] =
124 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
125  0x07, 0x03, 0x01, 0x00};
126
127 #define LSB     0
128 #define MSB16   1
129 #define MSB24   2
130 #define MSB32   3
131
132 /*-----------------------------------------------------------------*/
133 /* emitcode - writes the code into a file : for now it is simple    */
134 /*-----------------------------------------------------------------*/
135 static void
136 emitcode (char *inst, char *fmt,...)
137 {
138   va_list ap;
139   char lb[INITIAL_INLINEASM];
140   char *lbp = lb;
141
142   va_start (ap, fmt);
143
144   if (inst && *inst)
145     {
146       if (fmt && *fmt)
147         sprintf (lb, "%s\t", inst);
148       else
149         sprintf (lb, "%s", inst);
150       vsprintf (lb + (strlen (lb)), fmt, ap);
151     }
152   else
153     vsprintf (lb, fmt, ap);
154
155   while (isspace (*lbp))
156     lbp++;
157
158   if (lbp && *lbp)
159     lineCurr = (lineCurr ?
160                 connectLine (lineCurr, newLineNode (lb)) :
161                 (lineHead = newLineNode (lb)));
162   lineCurr->isInline = _G.inLine;
163   lineCurr->isDebug = _G.debugLine;
164   va_end (ap);
165 }
166
167 /*-----------------------------------------------------------------*/
168 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
169 /*-----------------------------------------------------------------*/
170 static regs *
171 getFreePtr (iCode * ic, asmop ** aopp, bool result)
172 {
173   bool r0iu = FALSE, r1iu = FALSE;
174   bool r0ou = FALSE, r1ou = FALSE;
175
176   /* the logic: if r0 & r1 used in the instruction
177      then we are in trouble otherwise */
178
179   /* first check if r0 & r1 are used by this
180      instruction, in which case we are in trouble */
181   r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
182   r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
183   if (r0iu && r1iu) {
184       goto endOfWorld;
185     }
186
187   r0ou = bitVectBitValue (ic->rMask, R0_IDX);
188   r1ou = bitVectBitValue (ic->rMask, R1_IDX);
189
190   /* if no usage of r0 then return it */
191   if (!r0iu && !r0ou)
192     {
193       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
194       (*aopp)->type = AOP_R0;
195
196       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
197     }
198
199   /* if no usage of r1 then return it */
200   if (!r1iu && !r1ou)
201     {
202       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
203       (*aopp)->type = AOP_R1;
204
205       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
206     }
207
208   /* now we know they both have usage */
209   /* if r0 not used in this instruction */
210   if (!r0iu)
211     {
212       /* push it if not already pushed */
213       if (!_G.r0Pushed)
214         {
215           emitcode ("push", "%s",
216                     ds390_regWithIdx (R0_IDX)->dname);
217           _G.r0Pushed++;
218         }
219
220       ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
221       (*aopp)->type = AOP_R0;
222
223       return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
224     }
225
226   /* if r1 not used then */
227
228   if (!r1iu)
229     {
230       /* push it if not already pushed */
231       if (!_G.r1Pushed)
232         {
233           emitcode ("push", "%s",
234                     ds390_regWithIdx (R1_IDX)->dname);
235           _G.r1Pushed++;
236         }
237
238       ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
239       (*aopp)->type = AOP_R1;
240       return ds390_regWithIdx (R1_IDX);
241     }
242
243 endOfWorld:
244   /* I said end of world but not quite end of world yet */
245   /* if this is a result then we can push it on the stack */
246   if (result)
247     {
248       (*aopp)->type = AOP_STK;
249       return NULL;
250     }
251
252   /* other wise this is true end of the world */
253   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
254           "getFreePtr should never reach here");
255   exit (1);
256 }
257
258 /*-----------------------------------------------------------------*/
259 /* newAsmop - creates a new asmOp                                  */
260 /*-----------------------------------------------------------------*/
261 static asmop *
262 newAsmop (short type)
263 {
264   asmop *aop;
265
266   aop = Safe_calloc (1, sizeof (asmop));
267   aop->type = type;
268   return aop;
269 }
270
271 static int _currentDPS;         /* Current processor DPS. */
272 static int _desiredDPS;         /* DPS value compiler thinks we should be using. */
273 static int _lazyDPS = 0;        /* if non-zero, we are doing lazy evaluation of DPS changes. */
274
275 /*-----------------------------------------------------------------*/
276 /* genSetDPTR: generate code to select which DPTR is in use (zero  */
277 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390     */
278 /* alternate DPTR (DPL1/DPH1/DPX1).          */
279 /*-----------------------------------------------------------------*/
280 static void
281 genSetDPTR (int n)
282 {
283
284   /* If we are doing lazy evaluation, simply note the desired
285    * change, but don't emit any code yet.
286    */
287   if (_lazyDPS)
288     {
289       _desiredDPS = n;
290       return;
291     }
292
293   if (!n)
294     {
295       emitcode ("mov", "dps, #0x00");
296     }
297   else
298     {
299       TR_DPTR("#1");
300       emitcode ("mov", "dps, #0x01");
301     }
302 }
303
304 /*-----------------------------------------------------------------*/
305 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
306 /*                   */
307 /* Any code that operates on DPTR (NB: not on the individual     */
308 /* components, like DPH) *must* call _flushLazyDPS() before using  */
309 /* DPTR within a lazy DPS evaluation block.        */
310 /*                   */
311 /* Note that aopPut and aopGet already contain the proper calls to */
312 /* _flushLazyDPS, so it is safe to use these calls within a lazy   */
313 /* DPS evaluation block.             */
314 /*                   */
315 /* Also, _flushLazyDPS must be called before any flow control      */
316 /* operations that could potentially branch out of the block.    */
317 /*                         */
318 /* Lazy DPS evaluation is simply an optimization (though an      */
319 /* important one), so if in doubt, leave it out.       */
320 /*-----------------------------------------------------------------*/
321 static void
322 _startLazyDPSEvaluation (void)
323 {
324   _currentDPS = 0;
325   _desiredDPS = 0;
326 #ifdef BETTER_LITERAL_SHIFT  
327   _lazyDPS++;
328 #else
329   _lazyDPS = 1;
330 #endif  
331 }
332
333 /*-----------------------------------------------------------------*/
334 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
335 /* desired one. Call before using DPTR within a lazy DPS evaluation */
336 /* block.                */
337 /*-----------------------------------------------------------------*/
338 static void
339 _flushLazyDPS (void)
340 {
341   if (!_lazyDPS)
342     {
343       /* nothing to do. */
344       return;
345     }
346
347   if (_desiredDPS != _currentDPS)
348     {
349       if (_desiredDPS)
350         {
351           emitcode ("inc", "dps");
352         }
353       else
354         {
355           emitcode ("dec", "dps");
356         }
357       _currentDPS = _desiredDPS;
358     }
359 }
360
361 /*-----------------------------------------------------------------*/
362 /* _endLazyDPSEvaluation: end lazy DPS evaluation block.     */
363 /*                   */
364 /* Forces us back to the safe state (standard DPTR selected).    */
365 /*-----------------------------------------------------------------*/
366 static void
367 _endLazyDPSEvaluation (void)
368 {
369 #ifdef BETTER_LITERAL_SHIFT  
370   _lazyDPS--;
371 #else
372   _lazyDPS = 0;
373 #endif    
374   if (!_lazyDPS)
375   {
376     if (_currentDPS)
377     {
378       genSetDPTR (0);
379       _flushLazyDPS ();
380     }
381     _currentDPS = 0;
382     _desiredDPS = 0;
383   }
384 }
385
386
387
388 /*-----------------------------------------------------------------*/
389 /* pointerCode - returns the code for a pointer type               */
390 /*-----------------------------------------------------------------*/
391 static int
392 pointerCode (sym_link * etype)
393 {
394
395   return PTR_TYPE (SPEC_OCLS (etype));
396
397 }
398
399 /*-----------------------------------------------------------------*/
400 /* aopForSym - for a true symbol                                   */
401 /*-----------------------------------------------------------------*/
402 static asmop *
403 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
404 {
405   asmop *aop;
406   memmap *space = SPEC_OCLS (sym->etype);
407
408   /* if already has one */
409   if (sym->aop)
410     return sym->aop;
411
412   /* assign depending on the storage class */
413   /* if it is on the stack or indirectly addressable */
414   /* space we need to assign either r0 or r1 to it   */
415   if ((sym->onStack && !options.stack10bit) || sym->iaccess)
416     {
417       sym->aop = aop = newAsmop (0);
418       aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
419       aop->size = getSize (sym->type);
420
421       /* now assign the address of the variable to
422          the pointer register */
423       if (aop->type != AOP_STK)
424         {
425
426           if (sym->onStack)
427             {
428               if (_G.accInUse)
429                 emitcode ("push", "acc");
430
431               emitcode ("mov", "a,_bp");
432               emitcode ("add", "a,#0x%02x",
433                         ((sym->stack < 0) ?
434                          ((char) (sym->stack - _G.nRegsSaved)) :
435                          ((char) sym->stack)) & 0xff);
436               emitcode ("mov", "%s,a",
437                         aop->aopu.aop_ptr->name);
438
439               if (_G.accInUse)
440                 emitcode ("pop", "acc");
441             }
442           else
443             emitcode ("mov", "%s,#%s",
444                       aop->aopu.aop_ptr->name,
445                       sym->rname);
446           aop->paged = space->paged;
447         }
448       else
449         aop->aopu.aop_stk = sym->stack;
450       return aop;
451     }
452
453   if (sym->onStack && options.stack10bit)
454     {
455       /* It's on the 10 bit stack, which is located in
456        * far data space.
457        */
458
459       if (_G.accInUse)
460         emitcode ("push", "acc");
461
462       emitcode ("mov", "a,_bp");
463       emitcode ("add", "a,#0x%02x",
464                 ((sym->stack < 0) ?
465                  ((char) (sym->stack - _G.nRegsSaved)) :
466                  ((char) sym->stack)) & 0xff);
467
468       if (useDP2)
469         {
470           if (options.model == MODEL_FLAT24)
471             emitcode ("mov", "dpx1,#0x40");
472           TR_DPTR("#2");
473           emitcode ("mov", "dph1,#0x00");
474           emitcode ("mov", "dpl1, a");
475         }
476       else
477         {
478           if (options.model == MODEL_FLAT24)
479             emitcode ("mov", "dpx,#0x40");
480           emitcode ("mov", "dph,#0x00");
481           emitcode ("mov", "dpl, a");
482         }
483
484       if (_G.accInUse)
485         emitcode ("pop", "acc");
486
487       sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
488       aop->size = getSize (sym->type);
489       return aop;
490     }
491
492   /* if in bit space */
493   if (IN_BITSPACE (space))
494     {
495       sym->aop = aop = newAsmop (AOP_CRY);
496       aop->aopu.aop_dir = sym->rname;
497       aop->size = getSize (sym->type);
498       return aop;
499     }
500   /* if it is in direct space */
501   if (IN_DIRSPACE (space))
502     {
503       sym->aop = aop = newAsmop (AOP_DIR);
504       aop->aopu.aop_dir = sym->rname;
505       aop->size = getSize (sym->type);
506       return aop;
507     }
508
509   /* special case for a function */
510   if (IS_FUNC (sym->type))
511     {
512       sym->aop = aop = newAsmop (AOP_IMMD);
513       aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
514       strcpy (aop->aopu.aop_immd, sym->rname);
515       aop->size = FPTRSIZE;
516       return aop;
517     }
518
519   /* only remaining is far space */
520   /* in which case DPTR gets the address */
521   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
522   if (useDP2)
523     {
524       genSetDPTR (1);
525       _flushLazyDPS ();
526       emitcode ("mov", "dptr,#%s", sym->rname);
527       genSetDPTR (0);
528     }
529   else
530     {
531       emitcode ("mov", "dptr,#%s", sym->rname);
532     }
533   aop->size = getSize (sym->type);
534
535   /* if it is in code space */
536   if (IN_CODESPACE (space))
537     aop->code = 1;
538
539   return aop;
540 }
541
542 /*-----------------------------------------------------------------*/
543 /* aopForRemat - rematerialzes an object                           */
544 /*-----------------------------------------------------------------*/
545 static asmop *
546 aopForRemat (symbol * sym)
547 {
548   iCode *ic = sym->rematiCode;
549   asmop *aop = newAsmop (AOP_IMMD);
550
551   int val = 0;
552
553   for (;;)
554     {
555       if (ic->op == '+')
556         val += (int) operandLitValue (IC_RIGHT (ic));
557       else if (ic->op == '-')
558         val -= (int) operandLitValue (IC_RIGHT (ic));
559       else
560         break;
561
562       ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
563     }
564
565   if (val)
566     sprintf (buffer, "(%s %c 0x%04x)",
567              OP_SYMBOL (IC_LEFT (ic))->rname,
568              val >= 0 ? '+' : '-',
569              abs (val) & 0xffff);
570   else
571     strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
572
573   aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
574   strcpy (aop->aopu.aop_immd, buffer);
575   return aop;
576 }
577
578 /*-----------------------------------------------------------------*/
579 /* regsInCommon - two operands have some registers in common       */
580 /*-----------------------------------------------------------------*/
581 static bool
582 regsInCommon (operand * op1, operand * op2)
583 {
584   symbol *sym1, *sym2;
585   int i;
586
587   /* if they have registers in common */
588   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
589     return FALSE;
590
591   sym1 = OP_SYMBOL (op1);
592   sym2 = OP_SYMBOL (op2);
593
594   if (sym1->nRegs == 0 || sym2->nRegs == 0)
595     return FALSE;
596
597   for (i = 0; i < sym1->nRegs; i++)
598     {
599       int j;
600       if (!sym1->regs[i])
601         continue;
602
603       for (j = 0; j < sym2->nRegs; j++)
604         {
605           if (!sym2->regs[j])
606             continue;
607
608           if (sym2->regs[j] == sym1->regs[i])
609             return TRUE;
610         }
611     }
612
613   return FALSE;
614 }
615
616 /*-----------------------------------------------------------------*/
617 /* operandsEqu - equivalent                                        */
618 /*-----------------------------------------------------------------*/
619 static bool
620 operandsEqu (operand * op1, operand * op2)
621 {
622   symbol *sym1, *sym2;
623
624   /* if they not symbols */
625   if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
626     return FALSE;
627
628   sym1 = OP_SYMBOL (op1);
629   sym2 = OP_SYMBOL (op2);
630
631   /* if both are itemps & one is spilt
632      and the other is not then false */
633   if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
634       sym1->isspilt != sym2->isspilt)
635     return FALSE;
636
637   /* if they are the same */
638   if (sym1 == sym2)
639     return TRUE;
640
641   if (strcmp (sym1->rname, sym2->rname) == 0)
642     return TRUE;
643
644
645   /* if left is a tmp & right is not */
646   if (IS_ITEMP (op1) &&
647       !IS_ITEMP (op2) &&
648       sym1->isspilt &&
649       (sym1->usl.spillLoc == sym2))
650     return TRUE;
651
652   if (IS_ITEMP (op2) &&
653       !IS_ITEMP (op1) &&
654       sym2->isspilt &&
655       sym1->level > 0 &&
656       (sym2->usl.spillLoc == sym1))
657     return TRUE;
658
659   return FALSE;
660 }
661
662 /*-----------------------------------------------------------------*/
663 /* sameRegs - two asmops have the same registers                   */
664 /*-----------------------------------------------------------------*/
665 static bool
666 sameRegs (asmop * aop1, asmop * aop2)
667 {
668   int i;
669
670   if (aop1 == aop2)
671     {
672       if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
673         {
674           return FALSE;
675         }
676       return TRUE;
677     }
678
679   if (aop1->type != AOP_REG ||
680       aop2->type != AOP_REG)
681     return FALSE;
682
683   if (aop1->size != aop2->size)
684     return FALSE;
685
686   for (i = 0; i < aop1->size; i++)
687     if (aop1->aopu.aop_reg[i] !=
688         aop2->aopu.aop_reg[i])
689       return FALSE;
690
691   return TRUE;
692 }
693
694 /*-----------------------------------------------------------------*/
695 /* aopOp - allocates an asmop for an operand  :                    */
696 /*-----------------------------------------------------------------*/
697 static void
698 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
699 {
700   asmop *aop;
701   symbol *sym;
702   int i;
703
704   if (!op)
705     return;
706
707   /* if this a literal */
708   if (IS_OP_LITERAL (op))
709     {
710       op->aop = aop = newAsmop (AOP_LIT);
711       aop->aopu.aop_lit = op->operand.valOperand;
712       aop->size = getSize (operandType (op));
713       return;
714     }
715
716   /* if already has a asmop then continue */
717   if (op->aop)
718     return;
719
720   /* if the underlying symbol has a aop */
721   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
722     {
723       op->aop = OP_SYMBOL (op)->aop;
724       return;
725     }
726
727   /* if this is a true symbol */
728   if (IS_TRUE_SYMOP (op))
729     {
730       op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
731       return;
732     }
733
734   /* this is a temporary : this has
735      only four choices :
736      a) register
737      b) spillocation
738      c) rematerialize
739      d) conditional
740      e) can be a return use only */
741
742   sym = OP_SYMBOL (op);
743
744
745   /* if the type is a conditional */
746   if (sym->regType == REG_CND)
747     {
748       aop = op->aop = sym->aop = newAsmop (AOP_CRY);
749       aop->size = 0;
750       return;
751     }
752
753   /* if it is spilt then two situations
754      a) is rematerialize
755      b) has a spill location */
756   if (sym->isspilt || sym->nRegs == 0)
757     {
758
759       /* rematerialize it NOW */
760       if (sym->remat)
761         {
762           sym->aop = op->aop = aop =
763             aopForRemat (sym);
764           aop->size = getSize (sym->type);
765           return;
766         }
767
768       if (sym->accuse)
769         {
770           int i;
771           aop = op->aop = sym->aop = newAsmop (AOP_ACC);
772           aop->size = getSize (sym->type);
773           for (i = 0; i < 2; i++)
774             aop->aopu.aop_str[i] = accUse[i];
775           return;
776         }
777
778       if (sym->ruonly)
779         {
780           int i;
781
782           if (useDP2)
783             {
784               /* a AOP_STR uses DPTR, but DPTR is already in use;
785                * we're just hosed.
786                */
787               fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use!\n");
788             }
789
790           aop = op->aop = sym->aop = newAsmop (AOP_STR);
791           aop->size = getSize (sym->type);
792           for (i = 0; i < (int) fReturnSizeDS390; i++)
793             aop->aopu.aop_str[i] = fReturn[i];
794           return;
795         }
796
797       /* else spill location  */
798       sym->aop = op->aop = aop =
799         aopForSym (ic, sym->usl.spillLoc, result, useDP2);
800       aop->size = getSize (sym->type);
801       return;
802     }
803
804   /* must be in a register */
805   sym->aop = op->aop = aop = newAsmop (AOP_REG);
806   aop->size = sym->nRegs;
807   for (i = 0; i < sym->nRegs; i++)
808     aop->aopu.aop_reg[i] = sym->regs[i];
809 }
810
811 /*-----------------------------------------------------------------*/
812 /* freeAsmop - free up the asmop given to an operand               */
813 /*----------------------------------------------------------------*/
814 static void
815 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
816 {
817   asmop *aop;
818
819   if (!op)
820     aop = aaop;
821   else
822     aop = op->aop;
823
824   if (!aop)
825     return;
826
827   if (aop->freed)
828     goto dealloc;
829
830   aop->freed = 1;
831
832   /* depending on the asmop type only three cases need work AOP_RO
833      , AOP_R1 && AOP_STK */
834   switch (aop->type)
835     {
836     case AOP_R0:
837       if (_G.r0Pushed)
838         {
839           if (pop)
840             {
841               emitcode ("pop", "ar0");
842               _G.r0Pushed--;
843             }
844         }
845       bitVectUnSetBit (ic->rUsed, R0_IDX);
846       break;
847
848     case AOP_R1:
849       if (_G.r1Pushed)
850         {
851           if (pop)
852             {
853               emitcode ("pop", "ar1");
854               _G.r1Pushed--;
855             }
856         }
857       bitVectUnSetBit (ic->rUsed, R1_IDX);
858       break;
859
860     case AOP_STK:
861       {
862         int sz = aop->size;
863         int stk = aop->aopu.aop_stk + aop->size;
864         bitVectUnSetBit (ic->rUsed, R0_IDX);
865         bitVectUnSetBit (ic->rUsed, R1_IDX);
866
867         getFreePtr (ic, &aop, FALSE);
868
869         if (options.stack10bit)
870           {
871             /* I'm not sure what to do here yet... */
872             /* #STUB */
873             fprintf (stderr,
874                      "*** Warning: probably generating bad code for "
875                      "10 bit stack mode.\n");
876           }
877
878         if (stk)
879           {
880             emitcode ("mov", "a,_bp");
881             emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
882             emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
883           }
884         else
885           {
886             emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
887           }
888
889         while (sz--)
890           {
891             emitcode ("pop", "acc");
892             emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
893             if (!sz)
894               break;
895             emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
896           }
897         op->aop = aop;
898         freeAsmop (op, NULL, ic, TRUE);
899         if (_G.r0Pushed)
900           {
901             emitcode ("pop", "ar0");
902             _G.r0Pushed--;
903           }
904
905         if (_G.r1Pushed)
906           {
907             emitcode ("pop", "ar1");
908             _G.r1Pushed--;
909           }
910       }
911     }
912
913 dealloc:
914   /* all other cases just dealloc */
915   if (op)
916     {
917       op->aop = NULL;
918       if (IS_SYMOP (op))
919         {
920           OP_SYMBOL (op)->aop = NULL;
921           /* if the symbol has a spill */
922           if (SPIL_LOC (op))
923             SPIL_LOC (op)->aop = NULL;
924         }
925     }
926 }
927
928 /*------------------------------------------------------------------*/
929 /* aopGet - for fetching value of the aop                           */
930 /*                    */
931 /* Set canClobberACC if you are sure it is OK to clobber the value  */
932 /* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */
933 /* just less efficient.               */
934 /*------------------------------------------------------------------*/
935
936 static char *
937 aopGet (asmop * aop,
938         int offset,
939         bool bit16,
940         bool dname,
941         bool canClobberACC)
942 {
943   char *s = buffer;
944   char *rs;
945
946   /* offset is greater than
947      size then zero */
948   if (offset > (aop->size - 1) &&
949       aop->type != AOP_LIT)
950     return zero;
951
952   /* depending on type */
953   switch (aop->type)
954     {
955
956     case AOP_R0:
957     case AOP_R1:
958       /* if we need to increment it */
959       while (offset > aop->coff)
960         {
961           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
962           aop->coff++;
963         }
964
965       while (offset < aop->coff)
966         {
967           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
968           aop->coff--;
969         }
970
971       aop->coff = offset;
972       if (aop->paged)
973         {
974           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
975           return (dname ? "acc" : "a");
976         }
977       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
978       rs = Safe_calloc (1, strlen (s) + 1);
979       strcpy (rs, s);
980       return rs;
981
982     case AOP_DPTR:
983     case AOP_DPTR2:
984
985       if (aop->type == AOP_DPTR2)
986         {
987           genSetDPTR (1);
988           if (!canClobberACC)
989             {
990                     TR_AP("#1");
991                     emitcode ("xch", "a, %s", DP2_RESULT_REG);
992             }
993         }
994
995       _flushLazyDPS ();
996
997       while (offset > aop->coff)
998         {
999           emitcode ("inc", "dptr");
1000           aop->coff++;
1001         }
1002
1003       while (offset < aop->coff)
1004         {
1005           emitcode ("lcall", "__decdptr");
1006           aop->coff--;
1007         }
1008
1009       aop->coff = offset;
1010       if (aop->code)
1011         {
1012           emitcode ("clr", "a");
1013           emitcode ("movc", "a,@a+dptr");
1014         }
1015       else
1016         {
1017           emitcode ("movx", "a,@dptr");
1018         }
1019
1020       if (aop->type == AOP_DPTR2)
1021         {
1022           genSetDPTR (0);
1023           if (!canClobberACC)
1024             {
1025        TR_AP("#2");
1026               emitcode ("xch", "a, %s", DP2_RESULT_REG);
1027               return DP2_RESULT_REG;
1028             }
1029         }
1030       return (dname ? "acc" : "a");
1031
1032     case AOP_IMMD:
1033       if (bit16)
1034         sprintf (s, "#%s", aop->aopu.aop_immd);
1035       else if (offset)
1036         sprintf (s, "#(%s >> %d)",
1037                  aop->aopu.aop_immd,
1038                  offset * 8);
1039       else
1040         sprintf (s, "#%s",
1041                  aop->aopu.aop_immd);
1042       rs = Safe_calloc (1, strlen (s) + 1);
1043       strcpy (rs, s);
1044       return rs;
1045
1046     case AOP_DIR:
1047       if (offset)
1048         sprintf (s, "(%s + %d)",
1049                  aop->aopu.aop_dir,
1050                  offset);
1051       else
1052         sprintf (s, "%s", aop->aopu.aop_dir);
1053       rs = Safe_calloc (1, strlen (s) + 1);
1054       strcpy (rs, s);
1055       return rs;
1056
1057     case AOP_REG:
1058       if (dname)
1059         return aop->aopu.aop_reg[offset]->dname;
1060       else
1061         return aop->aopu.aop_reg[offset]->name;
1062
1063     case AOP_CRY:
1064       emitcode ("clr", "a");
1065       emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1066       emitcode ("rlc", "a");
1067       return (dname ? "acc" : "a");
1068
1069     case AOP_ACC:
1070       if (!offset && dname)
1071         return "acc";
1072       return aop->aopu.aop_str[offset];
1073
1074     case AOP_LIT:
1075       return aopLiteral (aop->aopu.aop_lit, offset);
1076
1077     case AOP_STR:
1078       aop->coff = offset;
1079       if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1080           dname)
1081         return "acc";
1082
1083       return aop->aopu.aop_str[offset];
1084
1085     }
1086
1087   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1088           "aopget got unsupported aop->type");
1089   exit (1);
1090 }
1091 /*-----------------------------------------------------------------*/
1092 /* aopPut - puts a string for a aop                                */
1093 /*-----------------------------------------------------------------*/
1094 static void
1095 aopPut (asmop * aop, char *s, int offset)
1096 {
1097   char *d = buffer;
1098
1099   if (aop->size && offset > (aop->size - 1))
1100     {
1101       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1102               "aopPut got offset > aop->size");
1103       exit (1);
1104     }
1105
1106   /* will assign value to value */
1107   /* depending on where it is ofcourse */
1108   switch (aop->type)
1109     {
1110     case AOP_DIR:
1111       if (offset)
1112         sprintf (d, "(%s + %d)",
1113                  aop->aopu.aop_dir, offset);
1114       else
1115         sprintf (d, "%s", aop->aopu.aop_dir);
1116
1117       if (strcmp (d, s))
1118         emitcode ("mov", "%s,%s", d, s);
1119
1120       break;
1121
1122     case AOP_REG:
1123       if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1124           strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1125         {
1126           if (*s == '@' ||
1127               strcmp (s, "r0") == 0 ||
1128               strcmp (s, "r1") == 0 ||
1129               strcmp (s, "r2") == 0 ||
1130               strcmp (s, "r3") == 0 ||
1131               strcmp (s, "r4") == 0 ||
1132               strcmp (s, "r5") == 0 ||
1133               strcmp (s, "r6") == 0 ||
1134               strcmp (s, "r7") == 0)
1135             emitcode ("mov", "%s,%s",
1136                       aop->aopu.aop_reg[offset]->dname, s);
1137           else
1138             emitcode ("mov", "%s,%s",
1139                       aop->aopu.aop_reg[offset]->name, s);
1140         }
1141       break;
1142
1143     case AOP_DPTR:
1144     case AOP_DPTR2:
1145
1146       if (aop->type == AOP_DPTR2)
1147         {
1148           genSetDPTR (1);
1149         }
1150       _flushLazyDPS ();
1151
1152       if (aop->code)
1153         {
1154           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1155                   "aopPut writting to code space");
1156           exit (1);
1157         }
1158
1159       while (offset > aop->coff)
1160         {
1161           aop->coff++;
1162           emitcode ("inc", "dptr");
1163         }
1164
1165       while (offset < aop->coff)
1166         {
1167           aop->coff--;
1168           emitcode ("lcall", "__decdptr");
1169         }
1170
1171       aop->coff = offset;
1172
1173       /* if not in accumulater */
1174       MOVA (s);
1175
1176       emitcode ("movx", "@dptr,a");
1177
1178       if (aop->type == AOP_DPTR2)
1179         {
1180           genSetDPTR (0);
1181         }
1182       break;
1183
1184     case AOP_R0:
1185     case AOP_R1:
1186       while (offset > aop->coff)
1187         {
1188           aop->coff++;
1189           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1190         }
1191       while (offset < aop->coff)
1192         {
1193           aop->coff--;
1194           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1195         }
1196       aop->coff = offset;
1197
1198       if (aop->paged)
1199         {
1200           MOVA (s);
1201           emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1202
1203         }
1204       else if (*s == '@')
1205         {
1206           MOVA (s);
1207           emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1208         }
1209       else if (strcmp (s, "r0") == 0 ||
1210                strcmp (s, "r1") == 0 ||
1211                strcmp (s, "r2") == 0 ||
1212                strcmp (s, "r3") == 0 ||
1213                strcmp (s, "r4") == 0 ||
1214                strcmp (s, "r5") == 0 ||
1215                strcmp (s, "r6") == 0 ||
1216                strcmp (s, "r7") == 0)
1217         {
1218           char buffer[10];
1219           sprintf (buffer, "a%s", s);
1220           emitcode ("mov", "@%s,%s",
1221                     aop->aopu.aop_ptr->name, buffer);
1222         }
1223       else
1224         emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1225
1226       break;
1227
1228     case AOP_STK:
1229       if (strcmp (s, "a") == 0)
1230         emitcode ("push", "acc");
1231       else
1232         emitcode ("push", "%s", s);
1233
1234       break;
1235
1236     case AOP_CRY:
1237       /* if bit variable */
1238       if (!aop->aopu.aop_dir)
1239         {
1240           emitcode ("clr", "a");
1241           emitcode ("rlc", "a");
1242         }
1243       else
1244         {
1245           if (s == zero)
1246             emitcode ("clr", "%s", aop->aopu.aop_dir);
1247           else if (s == one)
1248             emitcode ("setb", "%s", aop->aopu.aop_dir);
1249           else if (!strcmp (s, "c"))
1250             emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1251           else
1252             {
1253               if (strcmp (s, "a"))
1254                 {
1255                   MOVA (s);
1256                 }
1257               {
1258                 symbol *lbl = newiTempLabel (NULL);
1259                 emitcode ("clr", "c");
1260                 emitcode ("jz", "%05d$", lbl->key + 100);
1261                 emitcode ("cpl", "c");
1262                 emitcode ("", "%05d$:", lbl->key + 100);
1263                 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1264               }
1265             }
1266         }
1267       break;
1268
1269     case AOP_STR:
1270       aop->coff = offset;
1271       if (strcmp (aop->aopu.aop_str[offset], s))
1272         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1273       break;
1274
1275     case AOP_ACC:
1276       aop->coff = offset;
1277       if (!offset && (strcmp (s, "acc") == 0))
1278         break;
1279
1280       if (strcmp (aop->aopu.aop_str[offset], s))
1281         emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1282       break;
1283
1284     default:
1285       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1286               "aopPut got unsupported aop->type");
1287       exit (1);
1288     }
1289
1290 }
1291
1292
1293 /*--------------------------------------------------------------------*/
1294 /* reAdjustPreg - points a register back to where it should (coff==0) */
1295 /*--------------------------------------------------------------------*/
1296 static void
1297 reAdjustPreg (asmop * aop)
1298 {
1299   if ((aop->coff==0) || (aop->size <= 1)) {
1300     return;
1301   }
1302
1303   switch (aop->type)
1304     {
1305     case AOP_R0:
1306     case AOP_R1:
1307       while (aop->coff--)
1308         emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1309       break;
1310     case AOP_DPTR:
1311     case AOP_DPTR2:
1312       if (aop->type == AOP_DPTR2)
1313         {
1314           genSetDPTR (1);
1315           _flushLazyDPS ();
1316         }
1317       while (aop->coff--)
1318         {
1319           emitcode ("lcall", "__decdptr");
1320         }
1321
1322       if (aop->type == AOP_DPTR2)
1323         {
1324           genSetDPTR (0);
1325         }
1326       break;
1327
1328     }
1329   aop->coff=0;
1330 }
1331
1332 #define AOP(op) op->aop
1333 #define AOP_TYPE(op) AOP(op)->type
1334 #define AOP_SIZE(op) AOP(op)->size
1335 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1336                        AOP_TYPE(x) == AOP_R0))
1337
1338 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
1339                         AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1340                          AOP(x)->paged))
1341
1342 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
1343                       (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1344                       x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1345
1346 /* Workaround for DS80C390 bug: div ab may return bogus results
1347  * if A is accessed in instruction immediately before the div.
1348  *
1349  * Will be fixed in B4 rev of processor, Dallas claims.
1350  */
1351
1352 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L)       \
1353     if (!AOP_NEEDSACC(RIGHT))         \
1354     {               \
1355       /* We can load A first, then B, since     \
1356        * B (the RIGHT operand) won't clobber A,   \
1357        * thus avoiding touching A right before the div. \
1358        */             \
1359       D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1360       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);     \
1361       MOVA(L);            \
1362       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1363     }               \
1364     else              \
1365     {               \
1366       /* Just stuff in a nop after loading A. */    \
1367       emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\
1368       L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE);   \
1369       MOVA(L);            \
1370       emitcode("nop", "; workaround for DS80C390 div bug.");  \
1371     }
1372
1373 /*-----------------------------------------------------------------*/
1374 /* genNotFloat - generates not for float operations              */
1375 /*-----------------------------------------------------------------*/
1376 static void
1377 genNotFloat (operand * op, operand * res)
1378 {
1379   int size, offset;
1380   char *l;
1381   symbol *tlbl;
1382
1383   D (emitcode (";", "genNotFloat ");
1384     );
1385
1386   /* we will put 127 in the first byte of
1387      the result */
1388   aopPut (AOP (res), "#127", 0);
1389   size = AOP_SIZE (op) - 1;
1390   offset = 1;
1391
1392   _startLazyDPSEvaluation ();
1393   l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE);
1394   MOVA (l);
1395
1396   while (size--)
1397     {
1398       emitcode ("orl", "a,%s",
1399                 aopGet (op->aop,
1400                         offset++, FALSE, FALSE, FALSE));
1401     }
1402   _endLazyDPSEvaluation ();
1403
1404   tlbl = newiTempLabel (NULL);
1405   aopPut (res->aop, one, 1);
1406   emitcode ("jz", "%05d$", (tlbl->key + 100));
1407   aopPut (res->aop, zero, 1);
1408   emitcode ("", "%05d$:", (tlbl->key + 100));
1409
1410   size = res->aop->size - 2;
1411   offset = 2;
1412   /* put zeros in the rest */
1413   while (size--)
1414     aopPut (res->aop, zero, offset++);
1415 }
1416
1417 /*-----------------------------------------------------------------*/
1418 /* opIsGptr: returns non-zero if the passed operand is       */
1419 /* a generic pointer type.             */
1420 /*-----------------------------------------------------------------*/
1421 static int
1422 opIsGptr (operand * op)
1423 {
1424   sym_link *type = operandType (op);
1425
1426   if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1427     {
1428       return 1;
1429     }
1430   return 0;
1431 }
1432
1433 /*-----------------------------------------------------------------*/
1434 /* getDataSize - get the operand data size                         */
1435 /*-----------------------------------------------------------------*/
1436 static int
1437 getDataSize (operand * op)
1438 {
1439   int size;
1440   size = AOP_SIZE (op);
1441   if (size == GPTRSIZE)
1442     {
1443       sym_link *type = operandType (op);
1444       if (IS_GENPTR (type))
1445         {
1446           /* generic pointer; arithmetic operations
1447            * should ignore the high byte (pointer type).
1448            */
1449           size--;
1450         }
1451     }
1452   return size;
1453 }
1454
1455 /*-----------------------------------------------------------------*/
1456 /* outAcc - output Acc                                             */
1457 /*-----------------------------------------------------------------*/
1458 static void
1459 outAcc (operand * result)
1460 {
1461   int size, offset;
1462   size = getDataSize (result);
1463   if (size)
1464     {
1465       aopPut (AOP (result), "a", 0);
1466       size--;
1467       offset = 1;
1468       /* unsigned or positive */
1469       while (size--)
1470         {
1471           aopPut (AOP (result), zero, offset++);
1472         }
1473     }
1474 }
1475
1476 /*-----------------------------------------------------------------*/
1477 /* outBitC - output a bit C                                        */
1478 /*-----------------------------------------------------------------*/
1479 static void
1480 outBitC (operand * result)
1481 {
1482   /* if the result is bit */
1483   if (AOP_TYPE (result) == AOP_CRY)
1484     {
1485       aopPut (AOP (result), "c", 0);
1486     }
1487   else
1488     {
1489       emitcode ("clr", "a");
1490       emitcode ("rlc", "a");
1491       outAcc (result);
1492     }
1493 }
1494
1495 /*-----------------------------------------------------------------*/
1496 /* toBoolean - emit code for orl a,operator(sizeop)                */
1497 /*-----------------------------------------------------------------*/
1498 static void
1499 toBoolean (operand * oper)
1500 {
1501   int   size = AOP_SIZE (oper) - 1;
1502   int   offset = 1;
1503   bool usedB = FALSE;
1504
1505   /* The generic part of a generic pointer should
1506    * not participate in it's truth value.
1507    *
1508    * i.e. 0x10000000 is zero.
1509    */
1510   if (opIsGptr (oper))
1511     {
1512       D (emitcode (";", "toBoolean: generic ptr special case.");
1513         );
1514       size--;
1515     }
1516
1517   _startLazyDPSEvaluation ();
1518   if (AOP_NEEDSACC (oper) && size)
1519     {
1520       usedB = TRUE;
1521       emitcode ("push", "b");
1522       emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE));
1523     }
1524   else
1525     {
1526       MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE));
1527     }
1528   while (size--)
1529     {
1530       if (usedB)
1531         {
1532           emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1533         }
1534       else
1535         {
1536           emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE));
1537         }
1538     }
1539   _endLazyDPSEvaluation ();
1540
1541   if (usedB)
1542     {
1543       emitcode ("mov", "a,b");
1544       emitcode ("pop", "b");
1545     }
1546 }
1547
1548
1549 /*-----------------------------------------------------------------*/
1550 /* genNot - generate code for ! operation                          */
1551 /*-----------------------------------------------------------------*/
1552 static void
1553 genNot (iCode * ic)
1554 {
1555   symbol *tlbl;
1556   sym_link *optype = operandType (IC_LEFT (ic));
1557
1558   D (emitcode (";", "genNot ");
1559     );
1560
1561   /* assign asmOps to operand & result */
1562   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1563   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1564
1565   /* if in bit space then a special case */
1566   if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1567     {
1568       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1569       emitcode ("cpl", "c");
1570       outBitC (IC_RESULT (ic));
1571       goto release;
1572     }
1573
1574   /* if type float then do float */
1575   if (IS_FLOAT (optype))
1576     {
1577       genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1578       goto release;
1579     }
1580
1581   toBoolean (IC_LEFT (ic));
1582
1583   tlbl = newiTempLabel (NULL);
1584   emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1585   emitcode ("", "%05d$:", tlbl->key + 100);
1586   outBitC (IC_RESULT (ic));
1587
1588 release:
1589   /* release the aops */
1590   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1591   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1592 }
1593
1594
1595 /*-----------------------------------------------------------------*/
1596 /* genCpl - generate code for complement                           */
1597 /*-----------------------------------------------------------------*/
1598 static void
1599 genCpl (iCode * ic)
1600 {
1601   int offset = 0;
1602   int size;
1603
1604   D (emitcode (";", "genCpl ");
1605     );
1606
1607
1608   /* assign asmOps to operand & result */
1609   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1610   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1611
1612   /* if both are in bit space then
1613      a special case */
1614   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1615       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1616     {
1617
1618       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1619       emitcode ("cpl", "c");
1620       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1621       goto release;
1622     }
1623
1624   size = AOP_SIZE (IC_RESULT (ic));
1625   _startLazyDPSEvaluation ();
1626   while (size--)
1627     {
1628       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1629       MOVA (l);
1630       emitcode ("cpl", "a");
1631       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1632     }
1633   _endLazyDPSEvaluation ();
1634
1635
1636 release:
1637   /* release the aops */
1638   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1639   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1640 }
1641
1642 /*-----------------------------------------------------------------*/
1643 /* genUminusFloat - unary minus for floating points                */
1644 /*-----------------------------------------------------------------*/
1645 static void
1646 genUminusFloat (operand * op, operand * result)
1647 {
1648   int size, offset = 0;
1649   char *l;
1650   /* for this we just need to flip the
1651      first it then copy the rest in place */
1652   D (emitcode (";", "genUminusFloat");
1653     );
1654
1655   _startLazyDPSEvaluation ();
1656   size = AOP_SIZE (op) - 1;
1657   l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE);
1658   MOVA (l);
1659
1660   emitcode ("cpl", "acc.7");
1661   aopPut (AOP (result), "a", 3);
1662
1663   while (size--)
1664     {
1665       aopPut (AOP (result),
1666               aopGet (AOP (op), offset, FALSE, FALSE, FALSE),
1667               offset);
1668       offset++;
1669     }
1670   _endLazyDPSEvaluation ();
1671 }
1672
1673 /*-----------------------------------------------------------------*/
1674 /* genUminus - unary minus code generation                         */
1675 /*-----------------------------------------------------------------*/
1676 static void
1677 genUminus (iCode * ic)
1678 {
1679   int offset, size;
1680   sym_link *optype, *rtype;
1681
1682   D (emitcode (";", "genUminus ");
1683     );
1684
1685
1686   /* assign asmops */
1687   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1688   aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
1689
1690   /* if both in bit space then special
1691      case */
1692   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1693       AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1694     {
1695
1696       emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1697       emitcode ("cpl", "c");
1698       emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1699       goto release;
1700     }
1701
1702   optype = operandType (IC_LEFT (ic));
1703   rtype = operandType (IC_RESULT (ic));
1704
1705   /* if float then do float stuff */
1706   if (IS_FLOAT (optype))
1707     {
1708       genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1709       goto release;
1710     }
1711
1712   /* otherwise subtract from zero */
1713   size = AOP_SIZE (IC_LEFT (ic));
1714   offset = 0;
1715   _startLazyDPSEvaluation ();
1716   while (size--)
1717     {
1718       char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE);
1719       if (!strcmp (l, "a"))
1720         {
1721           if (offset == 0)
1722             SETC;
1723           emitcode ("cpl", "a");
1724           emitcode ("addc", "a,#0");
1725         }
1726       else
1727         {
1728           if (offset == 0)
1729             CLRC;
1730           emitcode ("clr", "a");
1731           emitcode ("subb", "a,%s", l);
1732         }
1733       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1734     }
1735   _endLazyDPSEvaluation ();
1736
1737   /* if any remaining bytes in the result */
1738   /* we just need to propagate the sign   */
1739   if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1740     {
1741       emitcode ("rlc", "a");
1742       emitcode ("subb", "a,acc");
1743       while (size--)
1744         aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1745     }
1746
1747 release:
1748   /* release the aops */
1749   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1750   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1751 }
1752
1753 /*-----------------------------------------------------------------*/
1754 /* saveRegisters - will look for a call and save the registers     */
1755 /*-----------------------------------------------------------------*/
1756 static void
1757 saveRegisters (iCode * lic)
1758 {
1759   int i;
1760   iCode *ic;
1761   bitVect *rsave;
1762   sym_link *detype;
1763
1764   /* look for call */
1765   for (ic = lic; ic; ic = ic->next)
1766     if (ic->op == CALL || ic->op == PCALL)
1767       break;
1768
1769   if (!ic)
1770     {
1771       fprintf (stderr, "found parameter push with no function call\n");
1772       return;
1773     }
1774
1775   /* if the registers have been saved already then
1776      do nothing */
1777   if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type) ||
1778       IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))))
1779     return;
1780
1781   /* find the registers in use at this time
1782      and push them away to safety */
1783   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1784                          ic->rUsed);
1785
1786   ic->regsSaved = 1;
1787   if (options.useXstack)
1788     {
1789       if (bitVectBitValue (rsave, R0_IDX))
1790         emitcode ("mov", "b,r0");
1791       emitcode ("mov", "r0,%s", spname);
1792       for (i = 0; i < ds390_nRegs; i++)
1793         {
1794           if (bitVectBitValue (rsave, i))
1795             {
1796               if (i == R0_IDX)
1797                 emitcode ("mov", "a,b");
1798               else
1799                 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
1800               emitcode ("movx", "@r0,a");
1801               emitcode ("inc", "r0");
1802             }
1803         }
1804       emitcode ("mov", "%s,r0", spname);
1805       if (bitVectBitValue (rsave, R0_IDX))
1806         emitcode ("mov", "r0,b");
1807     }
1808   else
1809     for (i = 0; i < ds390_nRegs; i++)
1810       {
1811         if (bitVectBitValue (rsave, i))
1812           emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
1813       }
1814
1815   detype = getSpec (operandType (IC_LEFT (ic)));
1816 }
1817
1818 /*-----------------------------------------------------------------*/
1819 /* unsaveRegisters - pop the pushed registers                      */
1820 /*-----------------------------------------------------------------*/
1821 static void
1822 unsaveRegisters (iCode * ic)
1823 {
1824   int i;
1825   bitVect *rsave;
1826   /* find the registers in use at this time
1827      and push them away to safety */
1828   rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1829                          ic->rUsed);
1830
1831   if (options.useXstack)
1832     {
1833       emitcode ("mov", "r0,%s", spname);
1834       for (i = ds390_nRegs; i >= 0; i--)
1835         {
1836           if (bitVectBitValue (rsave, i))
1837             {
1838               emitcode ("dec", "r0");
1839               emitcode ("movx", "a,@r0");
1840               if (i == R0_IDX)
1841                 emitcode ("mov", "b,a");
1842               else
1843                 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
1844             }
1845
1846         }
1847       emitcode ("mov", "%s,r0", spname);
1848       if (bitVectBitValue (rsave, R0_IDX))
1849         emitcode ("mov", "r0,b");
1850     }
1851   else
1852     for (i = ds390_nRegs; i >= 0; i--)
1853       {
1854         if (bitVectBitValue (rsave, i))
1855           emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
1856       }
1857
1858 }
1859
1860
1861 /*-----------------------------------------------------------------*/
1862 /* pushSide -                */
1863 /*-----------------------------------------------------------------*/
1864 static void
1865 pushSide (operand * oper, int size)
1866 {
1867   int offset = 0;
1868   _startLazyDPSEvaluation ();
1869   while (size--)
1870     {
1871       char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE);
1872       if (AOP_TYPE (oper) != AOP_REG &&
1873           AOP_TYPE (oper) != AOP_DIR &&
1874           strcmp (l, "a"))
1875         {
1876           emitcode ("mov", "a,%s", l);
1877           emitcode ("push", "acc");
1878         }
1879       else
1880         emitcode ("push", "%s", l);
1881     }
1882   _endLazyDPSEvaluation ();
1883 }
1884
1885 /*-----------------------------------------------------------------*/
1886 /* assignResultValue -               */
1887 /*-----------------------------------------------------------------*/
1888 static void
1889 assignResultValue (operand * oper)
1890 {
1891   int offset = 0;
1892   int size = AOP_SIZE (oper);
1893
1894   _startLazyDPSEvaluation ();
1895   while (size--)
1896     {
1897       aopPut (AOP (oper), fReturn[offset], offset);
1898       offset++;
1899     }
1900   _endLazyDPSEvaluation ();
1901 }
1902
1903
1904 /*-----------------------------------------------------------------*/
1905 /* genXpush - pushes onto the external stack                       */
1906 /*-----------------------------------------------------------------*/
1907 static void
1908 genXpush (iCode * ic)
1909 {
1910   asmop *aop = newAsmop (0);
1911   regs *r;
1912   int size, offset = 0;
1913
1914   D (emitcode (";", "genXpush ");
1915     );
1916
1917   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1918   r = getFreePtr (ic, &aop, FALSE);
1919
1920
1921   emitcode ("mov", "%s,_spx", r->name);
1922
1923   size = AOP_SIZE (IC_LEFT (ic));
1924   _startLazyDPSEvaluation ();
1925   while (size--)
1926     {
1927
1928       char *l = aopGet (AOP (IC_LEFT (ic)),
1929                         offset++, FALSE, FALSE, TRUE);
1930       MOVA (l);
1931       emitcode ("movx", "@%s,a", r->name);
1932       emitcode ("inc", "%s", r->name);
1933
1934     }
1935   _endLazyDPSEvaluation ();
1936
1937
1938   emitcode ("mov", "_spx,%s", r->name);
1939
1940   freeAsmop (NULL, aop, ic, TRUE);
1941   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1942 }
1943
1944 /*-----------------------------------------------------------------*/
1945 /* genIpush - genrate code for pushing this gets a little complex  */
1946 /*-----------------------------------------------------------------*/
1947 static void
1948 genIpush (iCode * ic)
1949 {
1950   int size, offset = 0;
1951   char *l;
1952
1953   D (emitcode (";", "genIpush ");
1954     );
1955
1956   /* if this is not a parm push : ie. it is spill push
1957      and spill push is always done on the local stack */
1958   if (!ic->parmPush)
1959     {
1960
1961       /* and the item is spilt then do nothing */
1962       if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1963         return;
1964
1965       aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1966       size = AOP_SIZE (IC_LEFT (ic));
1967       /* push it on the stack */
1968       _startLazyDPSEvaluation ();
1969       while (size--)
1970         {
1971           l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE);
1972           if (*l == '#')
1973             {
1974               MOVA (l);
1975               l = "acc";
1976             }
1977           emitcode ("push", "%s", l);
1978         }
1979       _endLazyDPSEvaluation ();
1980       return;
1981     }
1982
1983   /* this is a paramter push: in this case we call
1984      the routine to find the call and save those
1985      registers that need to be saved */
1986   saveRegisters (ic);
1987
1988   /* if use external stack then call the external
1989      stack pushing routine */
1990   if (options.useXstack)
1991     {
1992       genXpush (ic);
1993       return;
1994     }
1995
1996   /* then do the push */
1997   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1998
1999   // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2000   size = AOP_SIZE (IC_LEFT (ic));
2001
2002   _startLazyDPSEvaluation ();
2003   while (size--)
2004     {
2005       l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE);
2006       if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2007           AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2008           strcmp (l, "a"))
2009         {
2010           emitcode ("mov", "a,%s", l);
2011           emitcode ("push", "acc");
2012         }
2013       else
2014         emitcode ("push", "%s", l);
2015     }
2016   _endLazyDPSEvaluation ();
2017
2018   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2019 }
2020
2021 /*-----------------------------------------------------------------*/
2022 /* genIpop - recover the registers: can happen only for spilling   */
2023 /*-----------------------------------------------------------------*/
2024 static void
2025 genIpop (iCode * ic)
2026 {
2027   int size, offset;
2028
2029   D (emitcode (";", "genIpop ");
2030     );
2031
2032
2033   /* if the temp was not pushed then */
2034   if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2035     return;
2036
2037   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2038   size = AOP_SIZE (IC_LEFT (ic));
2039   offset = (size - 1);
2040   _startLazyDPSEvaluation ();
2041   while (size--)
2042     {
2043       emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2044                                      FALSE, TRUE, TRUE));
2045     }
2046   _endLazyDPSEvaluation ();
2047
2048   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2049 }
2050
2051 /*-----------------------------------------------------------------*/
2052 /* unsaveRBank - restores the resgister bank from stack            */
2053 /*-----------------------------------------------------------------*/
2054 static void
2055 unsaveRBank (int bank, iCode * ic, bool popPsw)
2056 {
2057   int i;
2058   asmop *aop = NULL;
2059   regs *r = NULL;
2060
2061   if (options.useXstack)
2062   {
2063       if (!ic)
2064       {
2065           /* Assume r0 is available for use. */
2066           r = ds390_regWithIdx (R0_IDX);;          
2067       } 
2068       else
2069       {
2070           aop = newAsmop (0);
2071           r = getFreePtr (ic, &aop, FALSE);
2072       }
2073       emitcode ("mov", "%s,_spx", r->name);      
2074   }
2075   
2076   if (popPsw)
2077     {
2078       if (options.useXstack)
2079       {
2080           emitcode ("movx", "a,@%s", r->name);
2081           emitcode ("mov", "psw,a");
2082           emitcode ("dec", "%s", r->name);
2083         }
2084       else
2085       {
2086         emitcode ("pop", "psw");
2087       }
2088     }
2089
2090   for (i = (ds390_nRegs - 1); i >= 0; i--)
2091     {
2092       if (options.useXstack)
2093         {
2094           emitcode ("movx", "a,@%s", r->name);
2095           emitcode ("mov", "(%s+%d),a",
2096                     regs390[i].base, 8 * bank + regs390[i].offset);
2097           emitcode ("dec", "%s", r->name);
2098
2099         }
2100       else
2101         emitcode ("pop", "(%s+%d)",
2102                   regs390[i].base, 8 * bank + regs390[i].offset);
2103     }
2104
2105   if (options.useXstack)
2106     {
2107       emitcode ("mov", "_spx,%s", r->name);
2108     }
2109     
2110   if (aop)
2111   {
2112       freeAsmop (NULL, aop, ic, TRUE);  
2113   }    
2114 }
2115
2116 /*-----------------------------------------------------------------*/
2117 /* saveRBank - saves an entire register bank on the stack          */
2118 /*-----------------------------------------------------------------*/
2119 static void
2120 saveRBank (int bank, iCode * ic, bool pushPsw)
2121 {
2122   int i;
2123   asmop *aop = NULL;
2124   regs *r = NULL;
2125
2126   if (options.useXstack)
2127     {
2128         if (!ic)
2129         {
2130           /* Assume r0 is available for use. */
2131                   r = ds390_regWithIdx (R0_IDX);;
2132         }
2133         else
2134         {
2135           aop = newAsmop (0);
2136           r = getFreePtr (ic, &aop, FALSE);
2137         }
2138         emitcode ("mov", "%s,_spx", r->name);    
2139     }
2140
2141   for (i = 0; i < ds390_nRegs; i++)
2142     {
2143       if (options.useXstack)
2144         {
2145           emitcode ("inc", "%s", r->name);
2146           emitcode ("mov", "a,(%s+%d)",
2147                     regs390[i].base, 8 * bank + regs390[i].offset);
2148           emitcode ("movx", "@%s,a", r->name);
2149         }
2150       else
2151         emitcode ("push", "(%s+%d)",
2152                   regs390[i].base, 8 * bank + regs390[i].offset);
2153     }
2154
2155   if (pushPsw)
2156     {
2157       if (options.useXstack)
2158         {
2159           emitcode ("mov", "a,psw");
2160           emitcode ("movx", "@%s,a", r->name);
2161           emitcode ("inc", "%s", r->name);
2162           emitcode ("mov", "_spx,%s", r->name);
2163         }
2164       else
2165       {
2166         emitcode ("push", "psw");
2167       }
2168
2169       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2170     }
2171   
2172   if (aop)
2173   {
2174        freeAsmop (NULL, aop, ic, TRUE);
2175   }    
2176     
2177   if (ic)
2178   {  
2179       ic->bankSaved = 1;
2180   }
2181 }
2182
2183 /*-----------------------------------------------------------------*/
2184 /* genCall - generates a call statement                            */
2185 /*-----------------------------------------------------------------*/
2186 static void
2187 genCall (iCode * ic)
2188 {
2189   sym_link *dtype;
2190   bool restoreBank = FALSE;
2191   bool swapBanks = FALSE;
2192
2193   D (emitcode (";", "genCall "););
2194
2195   /* if we are calling a not _naked function that is not using
2196      the same register bank then we need to save the
2197      destination registers on the stack */
2198   dtype = operandType (IC_LEFT (ic));
2199   if (dtype && !IFFUNC_ISNAKED(dtype) &&
2200       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2201       IFFUNC_ISISR (currFunc->type))
2202   {
2203       if (!ic->bankSaved) 
2204       {
2205            /* This is unexpected; the bank should have been saved in
2206             * genFunction.
2207             */
2208            saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2209            restoreBank = TRUE;
2210       }
2211       swapBanks = TRUE;
2212   }
2213   
2214     /* if caller saves & we have not saved then */
2215     if (!ic->regsSaved)
2216       saveRegisters (ic);
2217   
2218   /* if send set is not empty the assign */
2219   /* We've saved all the registers we care about;
2220   * therefore, we may clobber any register not used
2221   * in the calling convention (i.e. anything not in
2222   * fReturn.
2223   */
2224   if (_G.sendSet)
2225     {
2226       iCode *sic;
2227
2228       for (sic = setFirstItem (_G.sendSet); sic;
2229            sic = setNextItem (_G.sendSet))
2230         {
2231           int size, offset = 0;
2232
2233           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2234           size = AOP_SIZE (IC_LEFT (sic));
2235
2236           _startLazyDPSEvaluation ();
2237           while (size--)
2238             {
2239               char *l = aopGet (AOP(IC_LEFT(sic)), offset,
2240                                 FALSE, FALSE, TRUE);
2241                 if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size)
2242                 {
2243                     emitcode("mov", "%s,%s", regs390[offset].name, l);
2244                 }
2245                 else if (strcmp (l, fReturn[offset]))
2246                 {
2247                     emitcode ("mov", "%s,%s",
2248                               fReturn[offset],
2249                               l);
2250                 }
2251               offset++;
2252             }
2253           _endLazyDPSEvaluation ();
2254           if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR)
2255           {
2256               size = AOP_SIZE (IC_LEFT (sic));
2257               if (size)
2258               {
2259                  size--;
2260               }
2261               while (size)
2262               {
2263                    size--;
2264                    emitcode("mov", "%s,%s",
2265                                     fReturn[size], regs390[size].name);
2266               }
2267           }
2268           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2269         }
2270       _G.sendSet = NULL;
2271     }  
2272     
2273   if (swapBanks)
2274   {
2275         emitcode ("mov", "psw,#0x%02x", 
2276            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2277   }
2278
2279   /* make the call */
2280   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2281                             OP_SYMBOL (IC_LEFT (ic))->rname :
2282                             OP_SYMBOL (IC_LEFT (ic))->name));
2283
2284   if (swapBanks)
2285   {
2286        emitcode ("mov", "psw,#0x%02x", 
2287           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2288   }
2289
2290   /* if we need assign a result value */
2291   if ((IS_ITEMP (IC_RESULT (ic)) &&
2292        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2293         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2294       IS_TRUE_SYMOP (IC_RESULT (ic)))
2295     {
2296       if (isOperandInFarSpace (IC_RESULT (ic))
2297           && getSize (operandType (IC_RESULT (ic))) <= 2)
2298         {
2299           int size = getSize (operandType (IC_RESULT (ic)));
2300
2301           /* Special case for 1 or 2 byte return in far space. */
2302           MOVA (fReturn[0]);
2303           if (size > 1)
2304             {
2305               emitcode ("mov", "b,%s", fReturn[1]);
2306             }
2307
2308           aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2309           aopPut (AOP (IC_RESULT (ic)), "a", 0);
2310
2311           if (size > 1)
2312             {
2313               aopPut (AOP (IC_RESULT (ic)), "b", 1);
2314             }
2315           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2316         }
2317       else
2318         {
2319           _G.accInUse++;
2320           aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2321           _G.accInUse--;
2322
2323           assignResultValue (IC_RESULT (ic));
2324
2325           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2326         }
2327     }
2328
2329   /* adjust the stack for parameters if
2330      required */
2331   if (ic->parmBytes)
2332     {
2333       int i;
2334       if (ic->parmBytes > 3)
2335         {
2336           emitcode ("mov", "a,%s", spname);
2337           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2338           emitcode ("mov", "%s,a", spname);
2339         }
2340       else
2341         for (i = 0; i < ic->parmBytes; i++)
2342           emitcode ("dec", "%s", spname);
2343     }
2344
2345   /* if we hade saved some registers then unsave them */
2346   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2347     unsaveRegisters (ic);
2348
2349   /* if register bank was saved then pop them */
2350   if (restoreBank)
2351     unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2352 }
2353
2354 /*-----------------------------------------------------------------*/
2355 /* genPcall - generates a call by pointer statement                */
2356 /*-----------------------------------------------------------------*/
2357 static void
2358 genPcall (iCode * ic)
2359 {
2360   sym_link *dtype;
2361   symbol *rlbl = newiTempLabel (NULL);
2362
2363   D (emitcode (";", "genPcall ");
2364     );
2365
2366
2367   /* if caller saves & we have not saved then */
2368   if (!ic->regsSaved)
2369     saveRegisters (ic);
2370
2371   /* if we are calling a function that is not using
2372      the same register bank then we need to save the
2373      destination registers on the stack */
2374   dtype = operandType (IC_LEFT (ic));
2375   if (dtype &&
2376       IFFUNC_ISISR (currFunc->type) &&
2377       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)))
2378     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2379
2380
2381   /* push the return address on to the stack */
2382   emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2383   emitcode ("push", "acc");
2384   emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2385   emitcode ("push", "acc");
2386
2387   if (options.model == MODEL_FLAT24)
2388     {
2389       emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
2390       emitcode ("push", "acc");
2391     }
2392
2393   /* now push the calling address */
2394   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2395
2396   pushSide (IC_LEFT (ic), FPTRSIZE);
2397
2398   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2399
2400   /* if send set is not empty the assign */
2401   if (_G.sendSet)
2402     {
2403       iCode *sic;
2404
2405       for (sic = setFirstItem (_G.sendSet); sic;
2406            sic = setNextItem (_G.sendSet))
2407         {
2408           int size, offset = 0;
2409
2410           aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2411           size = AOP_SIZE (IC_LEFT (sic));
2412           _startLazyDPSEvaluation ();
2413           while (size--)
2414             {
2415               char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2416                                 FALSE, FALSE, TRUE);
2417               if (strcmp (l, fReturn[offset]))
2418                 {
2419                   emitcode ("mov", "%s,%s",
2420                             fReturn[offset],
2421                             l);
2422                 }
2423               offset++;
2424             }
2425           _endLazyDPSEvaluation ();
2426           freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2427         }
2428       _G.sendSet = NULL;
2429     }
2430
2431   emitcode ("ret", "");
2432   emitcode ("", "%05d$:", (rlbl->key + 100));
2433
2434
2435   /* if we need assign a result value */
2436   if ((IS_ITEMP (IC_RESULT (ic)) &&
2437        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2438         OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2439       IS_TRUE_SYMOP (IC_RESULT (ic)))
2440     {
2441
2442       _G.accInUse++;
2443       aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2444       _G.accInUse--;
2445
2446       assignResultValue (IC_RESULT (ic));
2447
2448       freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2449     }
2450
2451   /* adjust the stack for parameters if
2452      required */
2453   if (ic->parmBytes)
2454     {
2455       int i;
2456       if (ic->parmBytes > 3)
2457         {
2458           emitcode ("mov", "a,%s", spname);
2459           emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2460           emitcode ("mov", "%s,a", spname);
2461         }
2462       else
2463         for (i = 0; i < ic->parmBytes; i++)
2464           emitcode ("dec", "%s", spname);
2465
2466     }
2467
2468   /* if register bank was saved then unsave them */
2469   if (dtype &&
2470       (FUNC_REGBANK (currFunc->type) !=
2471        FUNC_REGBANK (dtype)))
2472     unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2473
2474   /* if we hade saved some registers then
2475      unsave them */
2476   if (ic->regsSaved)
2477     unsaveRegisters (ic);
2478
2479 }
2480
2481 /*-----------------------------------------------------------------*/
2482 /* resultRemat - result  is rematerializable                       */
2483 /*-----------------------------------------------------------------*/
2484 static int
2485 resultRemat (iCode * ic)
2486 {
2487   if (SKIP_IC (ic) || ic->op == IFX)
2488     return 0;
2489
2490   if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2491     {
2492       symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2493       if (sym->remat && !POINTER_SET (ic))
2494         return 1;
2495     }
2496
2497   return 0;
2498 }
2499
2500 #if defined(__BORLANDC__) || defined(_MSC_VER)
2501 #define STRCASECMP stricmp
2502 #else
2503 #define STRCASECMP strcasecmp
2504 #endif
2505
2506 /*-----------------------------------------------------------------*/
2507 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2508 /*-----------------------------------------------------------------*/
2509 static bool
2510 inExcludeList (char *s)
2511 {
2512   int i = 0;
2513
2514   if (options.excludeRegs[i] &&
2515       STRCASECMP (options.excludeRegs[i], "none") == 0)
2516     return FALSE;
2517
2518   for (i = 0; options.excludeRegs[i]; i++)
2519     {
2520       if (options.excludeRegs[i] &&
2521           STRCASECMP (s, options.excludeRegs[i]) == 0)
2522         return TRUE;
2523     }
2524   return FALSE;
2525 }
2526
2527 /*-----------------------------------------------------------------*/
2528 /* genFunction - generated code for function entry                 */
2529 /*-----------------------------------------------------------------*/
2530 static void
2531 genFunction (iCode * ic)
2532 {
2533   symbol *sym;
2534   sym_link *ftype;
2535   bool   switchedPSW = FALSE;
2536
2537   D (emitcode (";", "genFunction "););
2538
2539   _G.nRegsSaved = 0;
2540   /* create the function header */
2541   emitcode (";", "-----------------------------------------");
2542   emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2543   emitcode (";", "-----------------------------------------");
2544
2545   emitcode ("", "%s:", sym->rname);
2546   ftype = operandType (IC_LEFT (ic));
2547
2548   if (IFFUNC_ISNAKED(ftype))
2549   {
2550       emitcode(";", "naked function: no prologue.");
2551       return;
2552   }
2553
2554   /* if critical function then turn interrupts off */
2555   if (IFFUNC_ISCRITICAL (ftype))
2556     emitcode ("clr", "ea");
2557
2558   /* here we need to generate the equates for the
2559      register bank if required */
2560   if (FUNC_REGBANK (ftype) != rbank)
2561     {
2562       int i;
2563
2564       rbank = FUNC_REGBANK (ftype);
2565       for (i = 0; i < ds390_nRegs; i++)
2566         {
2567           if (strcmp (regs390[i].base, "0") == 0)
2568             emitcode ("", "%s = 0x%02x",
2569                       regs390[i].dname,
2570                       8 * rbank + regs390[i].offset);
2571           else
2572             emitcode ("", "%s = %s + 0x%02x",
2573                       regs390[i].dname,
2574                       regs390[i].base,
2575                       8 * rbank + regs390[i].offset);
2576         }
2577     }
2578
2579   /* if this is an interrupt service routine then
2580      save acc, b, dpl, dph  */
2581   if (IFFUNC_ISISR (sym->type))
2582     {
2583
2584       if (!inExcludeList ("acc"))
2585         emitcode ("push", "acc");
2586       if (!inExcludeList ("b"))
2587         emitcode ("push", "b");
2588       if (!inExcludeList ("dpl"))
2589         emitcode ("push", "dpl");
2590       if (!inExcludeList ("dph"))
2591         emitcode ("push", "dph");
2592       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2593         {
2594           emitcode ("push", "dpx");
2595           /* Make sure we're using standard DPTR */
2596           emitcode ("push", "dps");
2597           emitcode ("mov", "dps, #0x00");
2598           if (options.stack10bit)
2599             {
2600               /* This ISR could conceivably use DPTR2. Better save it. */
2601               emitcode ("push", "dpl1");
2602               emitcode ("push", "dph1");
2603               emitcode ("push", "dpx1");
2604               emitcode ("push",  DP2_RESULT_REG);
2605             }
2606         }
2607       /* if this isr has no bank i.e. is going to
2608          run with bank 0 , then we need to save more
2609          registers :-) */
2610       if (!FUNC_REGBANK (sym->type))
2611         {
2612
2613           /* if this function does not call any other
2614              function then we can be economical and
2615              save only those registers that are used */
2616           if (!IFFUNC_HASFCALL(sym->type))
2617             {
2618               int i;
2619
2620               /* if any registers used */
2621               if (sym->regsUsed)
2622                 {
2623                   /* save the registers used */
2624                   for (i = 0; i < sym->regsUsed->size; i++)
2625                     {
2626                       if (bitVectBitValue (sym->regsUsed, i) ||
2627                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2628                         emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2629                     }
2630                 }
2631
2632             }
2633           else
2634             {
2635               /* this function has  a function call cannot
2636                  determines register usage so we will have to push the
2637                  entire bank */
2638               saveRBank (0, ic, FALSE);
2639             }
2640         }
2641         else
2642         {
2643             /* This ISR uses a non-zero bank.
2644              *
2645              * We assume that the bank is available for our
2646              * exclusive use.
2647              *
2648              * However, if this ISR calls a function which uses some
2649              * other bank, we must save that bank entirely.
2650              */
2651             unsigned long banksToSave = 0;
2652             
2653             if (IFFUNC_HASFCALL(sym->type))
2654             {
2655
2656 #define MAX_REGISTER_BANKS 4
2657
2658                 iCode *i;
2659                 int ix;
2660
2661                 for (i = ic; i; i = i->next)
2662                 {
2663                     if (i->op == ENDFUNCTION)
2664                     {
2665                         /* we got to the end OK. */
2666                         break;
2667                     }
2668                     
2669                     if (i->op == CALL)
2670                     {
2671                         sym_link *dtype;
2672                         
2673                         dtype = operandType (IC_LEFT(i));
2674                         if (dtype 
2675                          && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2676                         {
2677                              /* Mark this bank for saving. */
2678                              if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2679                              {
2680                                  werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2681                              }
2682                              else
2683                              {
2684                                  banksToSave |= (1 << FUNC_REGBANK(dtype));
2685                              }
2686                              
2687                              /* And note that we don't need to do it in 
2688                               * genCall.
2689                               */
2690                              i->bankSaved = 1;
2691                         }
2692                     }
2693                     if (i->op == PCALL)
2694                     {
2695                         /* This is a mess; we have no idea what
2696                          * register bank the called function might
2697                          * use.
2698                          *
2699                          * The only thing I can think of to do is
2700                          * throw a warning and hope.
2701                          */
2702                         werror(W_FUNCPTR_IN_USING_ISR);   
2703                     }
2704                 }
2705
2706                 if (banksToSave && options.useXstack)
2707                 {
2708                     /* Since we aren't passing it an ic, 
2709                      * saveRBank will assume r0 is available to abuse.
2710                      *
2711                      * So switch to our (trashable) bank now, so
2712                      * the caller's R0 isn't trashed.
2713                      */
2714                     emitcode ("push", "psw");
2715                     emitcode ("mov", "psw,#0x%02x", 
2716                               (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2717                     switchedPSW = TRUE;
2718                 }
2719                 
2720                 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2721                 {
2722                      if (banksToSave & (1 << ix))
2723                      {
2724                          saveRBank(ix, NULL, FALSE);
2725                      }
2726                 }
2727             }
2728             // jwk: this needs a closer look
2729             SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2730         }
2731     }
2732   else
2733     {
2734       /* if callee-save to be used for this function
2735          then save the registers being used in this function */
2736       if (IFFUNC_CALLEESAVES(sym->type))
2737         {
2738           int i;
2739
2740           /* if any registers used */
2741           if (sym->regsUsed)
2742             {
2743               /* save the registers used */
2744               for (i = 0; i < sym->regsUsed->size; i++)
2745                 {
2746                   if (bitVectBitValue (sym->regsUsed, i) ||
2747                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2748                     {
2749                       emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2750                       _G.nRegsSaved++;
2751                     }
2752                 }
2753             }
2754         }
2755     }
2756
2757   /* set the register bank to the desired value */
2758   if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
2759    && !switchedPSW)
2760     {
2761       emitcode ("push", "psw");
2762       emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2763     }
2764
2765   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2766     {
2767
2768       if (options.useXstack)
2769         {
2770           emitcode ("mov", "r0,%s", spname);
2771           emitcode ("mov", "a,_bp");
2772           emitcode ("movx", "@r0,a");
2773           emitcode ("inc", "%s", spname);
2774         }
2775       else
2776         {
2777           /* set up the stack */
2778           emitcode ("push", "_bp");     /* save the callers stack  */
2779         }
2780       emitcode ("mov", "_bp,%s", spname);
2781     }
2782
2783   /* adjust the stack for the function */
2784   if (sym->stack)
2785     {
2786
2787       int i = sym->stack;
2788       if (i > 256)
2789         werror (W_STACK_OVERFLOW, sym->name);
2790
2791       if (i > 3 && sym->recvSize < 4)
2792         {
2793
2794           emitcode ("mov", "a,sp");
2795           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2796           emitcode ("mov", "sp,a");
2797
2798         }
2799       else
2800         while (i--)
2801           emitcode ("inc", "sp");
2802     }
2803
2804   if (sym->xstack)
2805     {
2806
2807       emitcode ("mov", "a,_spx");
2808       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2809       emitcode ("mov", "_spx,a");
2810     }
2811
2812 }
2813
2814 /*-----------------------------------------------------------------*/
2815 /* genEndFunction - generates epilogue for functions               */
2816 /*-----------------------------------------------------------------*/
2817 static void
2818 genEndFunction (iCode * ic)
2819 {
2820   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2821
2822   D (emitcode (";", "genEndFunction "););
2823
2824   if (IFFUNC_ISNAKED(sym->type))
2825   {
2826       emitcode(";", "naked function: no epilogue.");
2827       return;
2828   }
2829
2830   if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2831     {
2832       emitcode ("mov", "%s,_bp", spname);
2833     }
2834
2835   /* if use external stack but some variables were
2836      added to the local stack then decrement the
2837      local stack */
2838   if (options.useXstack && sym->stack)
2839     {
2840       emitcode ("mov", "a,sp");
2841       emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2842       emitcode ("mov", "sp,a");
2843     }
2844
2845
2846   if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2847     {
2848       if (options.useXstack)
2849         {
2850           emitcode ("mov", "r0,%s", spname);
2851           emitcode ("movx", "a,@r0");
2852           emitcode ("mov", "_bp,a");
2853           emitcode ("dec", "%s", spname);
2854         }
2855       else
2856         {
2857           emitcode ("pop", "_bp");
2858         }
2859     }
2860
2861   /* restore the register bank  */
2862   if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2863   {
2864     if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2865      || !options.useXstack)
2866     {
2867         /* Special case of ISR using non-zero bank with useXstack
2868          * is handled below.
2869          */
2870         emitcode ("pop", "psw");
2871     }
2872   }
2873
2874   if (IFFUNC_ISISR (sym->type))
2875     {
2876
2877       /* now we need to restore the registers */
2878       /* if this isr has no bank i.e. is going to
2879          run with bank 0 , then we need to save more
2880          registers :-) */
2881       if (!FUNC_REGBANK (sym->type))
2882         {
2883           /* if this function does not call any other
2884              function then we can be economical and
2885              save only those registers that are used */
2886           if (!IFFUNC_HASFCALL(sym->type))
2887             {
2888               int i;
2889
2890               /* if any registers used */
2891               if (sym->regsUsed)
2892                 {
2893                   /* save the registers used */
2894                   for (i = sym->regsUsed->size; i >= 0; i--)
2895                     {
2896                       if (bitVectBitValue (sym->regsUsed, i) ||
2897                           (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2898                         emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2899                     }
2900                 }
2901
2902             }
2903           else
2904             {
2905               /* this function has  a function call cannot
2906                  determines register usage so we will have to pop the
2907                  entire bank */
2908               unsaveRBank (0, ic, FALSE);
2909             }
2910         }
2911         else
2912         {
2913             /* This ISR uses a non-zero bank.
2914              *
2915              * Restore any register banks saved by genFunction
2916              * in reverse order.
2917              */
2918           // jwk: this needs a closer look
2919             unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2920             int ix;
2921           
2922             for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2923             {
2924                 if (savedBanks & (1 << ix))
2925                 {
2926                     unsaveRBank(ix, NULL, FALSE);
2927                 }
2928             }
2929             
2930             if (options.useXstack)
2931             {
2932                 /* Restore bank AFTER calling unsaveRBank,
2933                  * since it can trash r0.
2934                  */
2935                 emitcode ("pop", "psw");
2936             }
2937         }
2938
2939       if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2940         {
2941           if (options.stack10bit)
2942             {
2943               emitcode ("pop", DP2_RESULT_REG);
2944               emitcode ("pop", "dpx1");
2945               emitcode ("pop", "dph1");
2946               emitcode ("pop", "dpl1");
2947             }
2948           emitcode ("pop", "dps");
2949           emitcode ("pop", "dpx");
2950         }
2951       if (!inExcludeList ("dph"))
2952         emitcode ("pop", "dph");
2953       if (!inExcludeList ("dpl"))
2954         emitcode ("pop", "dpl");
2955       if (!inExcludeList ("b"))
2956         emitcode ("pop", "b");
2957       if (!inExcludeList ("acc"))
2958         emitcode ("pop", "acc");
2959
2960       if (IFFUNC_ISCRITICAL (sym->type))
2961         emitcode ("setb", "ea");
2962
2963       /* if debug then send end of function */
2964       if (options.debug && currFunc) {
2965           _G.debugLine = 1;
2966           emitcode ("", "C$%s$%d$%d$%d ==.",
2967                     FileBaseName (ic->filename), currFunc->lastLine,
2968                     ic->level, ic->block);
2969           if (IS_STATIC (currFunc->etype))
2970             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2971           else
2972             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2973           _G.debugLine = 0;
2974         }
2975
2976       emitcode ("reti", "");
2977     }
2978   else
2979     {
2980       if (IFFUNC_ISCRITICAL (sym->type))
2981         emitcode ("setb", "ea");
2982
2983       if (IFFUNC_CALLEESAVES(sym->type))
2984         {
2985           int i;
2986
2987           /* if any registers used */
2988           if (sym->regsUsed)
2989             {
2990               /* save the registers used */
2991               for (i = sym->regsUsed->size; i >= 0; i--)
2992                 {
2993                   if (bitVectBitValue (sym->regsUsed, i) ||
2994                       (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2995                     emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2996                 }
2997             }
2998
2999         }
3000
3001       /* if debug then send end of function */
3002       if (options.debug && currFunc)
3003         {
3004           _G.debugLine = 1;
3005           emitcode ("", "C$%s$%d$%d$%d ==.",
3006                     FileBaseName (ic->filename), currFunc->lastLine,
3007                     ic->level, ic->block);
3008           if (IS_STATIC (currFunc->etype))
3009             emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3010           else
3011             emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3012           _G.debugLine = 0;
3013         }
3014
3015       emitcode ("ret", "");
3016     }
3017
3018 }
3019
3020 /*-----------------------------------------------------------------*/
3021 /* genRet - generate code for return statement                     */
3022 /*-----------------------------------------------------------------*/
3023 static void
3024 genRet (iCode * ic)
3025 {
3026   int size, offset = 0, pushed = 0;
3027
3028   D (emitcode (";", "genRet ");
3029     );
3030
3031   /* if we have no return value then
3032      just generate the "ret" */
3033   if (!IC_LEFT (ic))
3034     goto jumpret;
3035
3036   /* we have something to return then
3037      move the return value into place */
3038   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
3039   size = AOP_SIZE (IC_LEFT (ic));
3040
3041   _startLazyDPSEvaluation ();
3042   while (size--)
3043     {
3044       char *l;
3045       if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3046         {
3047           l = aopGet (AOP (IC_LEFT (ic)), offset++,
3048                       FALSE, TRUE, FALSE);
3049           emitcode ("push", "%s", l);
3050           pushed++;
3051         }
3052       else
3053         {
3054           /* Since A is the last element of fReturn,
3055            * is is OK to clobber it in the aopGet.
3056            */
3057           l = aopGet (AOP (IC_LEFT (ic)), offset,
3058                       FALSE, FALSE, TRUE);
3059           if (strcmp (fReturn[offset], l))
3060             emitcode ("mov", "%s,%s", fReturn[offset++], l);
3061         }
3062     }
3063   _endLazyDPSEvaluation ();
3064
3065   if (pushed)
3066     {
3067       while (pushed)
3068         {
3069           pushed--;
3070           if (strcmp (fReturn[pushed], "a"))
3071             emitcode ("pop", fReturn[pushed]);
3072           else
3073             emitcode ("pop", "acc");
3074         }
3075     }
3076   freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3077
3078 jumpret:
3079   /* generate a jump to the return label
3080      if the next is not the return statement */
3081   if (!(ic->next && ic->next->op == LABEL &&
3082         IC_LABEL (ic->next) == returnLabel))
3083
3084     emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3085
3086 }
3087
3088 /*-----------------------------------------------------------------*/
3089 /* genLabel - generates a label                                    */
3090 /*-----------------------------------------------------------------*/
3091 static void
3092 genLabel (iCode * ic)
3093 {
3094   /* special case never generate */
3095   if (IC_LABEL (ic) == entryLabel)
3096     return;
3097
3098   D (emitcode (";", "genLabel ");
3099     );
3100
3101   emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3102 }
3103
3104 /*-----------------------------------------------------------------*/
3105 /* genGoto - generates a ljmp                                      */
3106 /*-----------------------------------------------------------------*/
3107 static void
3108 genGoto (iCode * ic)
3109 {
3110   D (emitcode (";", "genGoto ");
3111     );
3112   emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3113 }
3114
3115 /*-----------------------------------------------------------------*/
3116 /* findLabelBackwards: walks back through the iCode chain looking  */
3117 /* for the given label. Returns number of iCode instructions     */
3118 /* between that label and given ic.          */
3119 /* Returns zero if label not found.          */
3120 /*-----------------------------------------------------------------*/
3121 static int
3122 findLabelBackwards (iCode * ic, int key)
3123 {
3124   int count = 0;
3125
3126   while (ic->prev)
3127     {
3128       ic = ic->prev;
3129       count++;
3130
3131       if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3132         {
3133           /* printf("findLabelBackwards = %d\n", count); */
3134           return count;
3135         }
3136     }
3137
3138   return 0;
3139 }
3140
3141 /*-----------------------------------------------------------------*/
3142 /* genPlusIncr :- does addition with increment if possible         */
3143 /*-----------------------------------------------------------------*/
3144 static bool
3145 genPlusIncr (iCode * ic)
3146 {
3147   unsigned int icount;
3148   unsigned int size = getDataSize (IC_RESULT (ic));
3149
3150   /* will try to generate an increment */
3151   /* if the right side is not a literal
3152      we cannot */
3153   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3154     return FALSE;
3155
3156   /* if the literal value of the right hand side
3157      is greater than 4 then it is not worth it */
3158   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3159     return FALSE;
3160
3161   /* if increment 16 bits in register */
3162   if (
3163        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3164        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3165        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3166        (size > 1) &&
3167        (icount == 1))
3168     {
3169       symbol *tlbl;
3170       int emitTlbl;
3171       int labelRange;
3172
3173       /* If the next instruction is a goto and the goto target
3174        * is <= 5 instructions previous to this, we can generate
3175        * jumps straight to that target.
3176        */
3177       if (ic->next && ic->next->op == GOTO
3178           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3179           && labelRange <= 5)
3180         {
3181           emitcode (";", "tail increment optimized (range %d)", labelRange);
3182           tlbl = IC_LABEL (ic->next);
3183           emitTlbl = 0;
3184         }
3185       else
3186         {
3187           tlbl = newiTempLabel (NULL);
3188           emitTlbl = 1;
3189         }
3190       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3191       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3192           IS_AOP_PREG (IC_RESULT (ic)))
3193         emitcode ("cjne", "%s,#0x00,%05d$"
3194                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3195                   ,tlbl->key + 100);
3196       else
3197         {
3198           emitcode ("clr", "a");
3199           emitcode ("cjne", "a,%s,%05d$"
3200                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3201                     ,tlbl->key + 100);
3202         }
3203
3204       emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3205       if (size > 2)
3206         {
3207           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3208               IS_AOP_PREG (IC_RESULT (ic)))
3209             emitcode ("cjne", "%s,#0x00,%05d$"
3210                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3211                       ,tlbl->key + 100);
3212           else
3213             emitcode ("cjne", "a,%s,%05d$"
3214                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3215                       ,tlbl->key + 100);
3216
3217           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3218         }
3219       if (size > 3)
3220         {
3221           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3222               IS_AOP_PREG (IC_RESULT (ic)))
3223             emitcode ("cjne", "%s,#0x00,%05d$"
3224                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3225                       ,tlbl->key + 100);
3226           else
3227             {
3228               emitcode ("cjne", "a,%s,%05d$"
3229                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3230                         ,tlbl->key + 100);
3231             }
3232           emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3233         }
3234
3235       if (emitTlbl)
3236         {
3237           emitcode ("", "%05d$:", tlbl->key + 100);
3238         }
3239       return TRUE;
3240     }
3241
3242   /* if the sizes are greater than 1 then we cannot */
3243   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3244       AOP_SIZE (IC_LEFT (ic)) > 1)
3245     return FALSE;
3246
3247   /* we can if the aops of the left & result match or
3248      if they are in registers and the registers are the
3249      same */
3250   if (
3251        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3252        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3253        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3254     {
3255
3256       if (icount > 3)
3257         {
3258           MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE));
3259           emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3260           aopPut (AOP (IC_RESULT (ic)), "a", 0);
3261         }
3262       else
3263         {
3264
3265           _startLazyDPSEvaluation ();
3266           while (icount--)
3267             {
3268               emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE));
3269             }
3270           _endLazyDPSEvaluation ();
3271         }
3272
3273       return TRUE;
3274     }
3275
3276   return FALSE;
3277 }
3278
3279 /*-----------------------------------------------------------------*/
3280 /* outBitAcc - output a bit in acc                                 */
3281 /*-----------------------------------------------------------------*/
3282 static void
3283 outBitAcc (operand * result)
3284 {
3285   symbol *tlbl = newiTempLabel (NULL);
3286   /* if the result is a bit */
3287   if (AOP_TYPE (result) == AOP_CRY)
3288     {
3289       aopPut (AOP (result), "a", 0);
3290     }
3291   else
3292     {
3293       emitcode ("jz", "%05d$", tlbl->key + 100);
3294       emitcode ("mov", "a,%s", one);
3295       emitcode ("", "%05d$:", tlbl->key + 100);
3296       outAcc (result);
3297     }
3298 }
3299
3300 /*-----------------------------------------------------------------*/
3301 /* genPlusBits - generates code for addition of two bits           */
3302 /*-----------------------------------------------------------------*/
3303 static void
3304 genPlusBits (iCode * ic)
3305 {
3306   D (emitcode (";", "genPlusBits ");
3307     );
3308   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3309     {
3310       symbol *lbl = newiTempLabel (NULL);
3311       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3312       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3313       emitcode ("cpl", "c");
3314       emitcode ("", "%05d$:", (lbl->key + 100));
3315       outBitC (IC_RESULT (ic));
3316     }
3317   else
3318     {
3319       emitcode ("clr", "a");
3320       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3321       emitcode ("rlc", "a");
3322       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3323       emitcode ("addc", "a,#0x00");
3324       outAcc (IC_RESULT (ic));
3325     }
3326 }
3327
3328 static void
3329 adjustArithmeticResult (iCode * ic)
3330 {
3331   if (opIsGptr (IC_RESULT (ic)) &&
3332       opIsGptr (IC_LEFT (ic)) &&
3333       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3334     {
3335       aopPut (AOP (IC_RESULT (ic)),
3336               aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3337               GPTRSIZE - 1);
3338     }
3339
3340   if (opIsGptr (IC_RESULT (ic)) &&
3341       opIsGptr (IC_RIGHT (ic)) &&
3342       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3343     {
3344       aopPut (AOP (IC_RESULT (ic)),
3345             aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE),
3346               GPTRSIZE - 1);
3347     }
3348
3349   if (opIsGptr (IC_RESULT (ic)) &&
3350       AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3351       AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3352       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3353       !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3354     {
3355       char buffer[5];
3356       sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3357       aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3358     }
3359 }
3360
3361 #if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
3362       // Please don't bring it back without a really good reason.
3363 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
3364 // (because all three operands are in far space).
3365 #define AOP_OP_3(ic) \
3366     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3367     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3368     aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3369               (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3370     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3371         AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3372     { \
3373         /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3374         fprintf(stderr,                                  \
3375                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3376     }
3377 #endif
3378
3379 // Macro to aopOp all three operands of an ic. If this cannot be done, 
3380 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3381 // will be set TRUE. The caller must then handle the case specially, noting
3382 // that the IC_RESULT operand is not aopOp'd.
3383 #define AOP_OP_3_NOFATAL(ic, rc) \
3384     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3385     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3386     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3387         isOperandInFarSpace(IC_RESULT(ic))) \
3388     { \
3389        /* No can do; DPTR & DPTR2 in use, and we need another. */ \
3390        rc = TRUE; \
3391     }  \
3392     else \
3393     { \
3394        aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \
3395                                      (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \
3396        rc = FALSE; \
3397        if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \
3398            AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
3399        { \
3400             /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
3401             fprintf(stderr,                                  \
3402                     "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
3403        } \
3404     }
3405
3406 // aopOp the left & right operands of an ic.
3407 #define AOP_OP_2(ic) \
3408     aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \
3409     aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR));
3410
3411 // convienience macro.
3412 #define AOP_SET_LOCALS(ic) \
3413     left = IC_LEFT(ic); \
3414     right = IC_RIGHT(ic); \
3415     result = IC_RESULT(ic);
3416
3417
3418 // Given an integer value of pushedSize bytes on the stack,
3419 // adjust it to be resultSize bytes, either by discarding
3420 // the most significant bytes or by zero-padding.
3421 //
3422 // On exit from this macro, pushedSize will have been adjusted to
3423 // equal resultSize, and ACC may be trashed.
3424 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize)            \
3425       /* If the pushed data is bigger than the result,          \
3426        * simply discard unused bytes. Icky, but works.          \
3427        */                                                       \
3428       while (pushedSize > resultSize)                           \
3429       {                                                         \
3430           D (emitcode (";", "discarding unused result byte."););\
3431           emitcode ("pop", "acc");                              \
3432           pushedSize--;                                         \
3433       }                                                         \
3434       if (pushedSize < resultSize)                              \
3435       {                                                         \
3436           emitcode ("clr", "a");                                \
3437           /* Conversly, we haven't pushed enough here.          \
3438            * just zero-pad, and all is well.                    \
3439            */                                                   \
3440           while (pushedSize < resultSize)                       \
3441           {                                                     \
3442               emitcode("push", "acc");                          \
3443               pushedSize++;                                     \
3444           }                                                     \
3445       }                                                         \
3446       assert(pushedSize == resultSize);
3447
3448 /*-----------------------------------------------------------------*/
3449 /* genPlus - generates code for addition                           */
3450 /*-----------------------------------------------------------------*/
3451 static void
3452 genPlus (iCode * ic)
3453 {
3454   int size, offset = 0;
3455   bool pushResult = FALSE;
3456   int rSize;
3457
3458   D (emitcode (";", "genPlus "););
3459
3460   /* special cases :- */
3461
3462   AOP_OP_3_NOFATAL (ic, pushResult);
3463   if (pushResult)
3464     {
3465       D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
3466     }
3467
3468   if (!pushResult)
3469     {
3470       /* if literal, literal on the right or
3471          if left requires ACC or right is already
3472          in ACC */
3473       if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
3474        || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
3475           || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3476         {
3477           operand *t = IC_RIGHT (ic);
3478           IC_RIGHT (ic) = IC_LEFT (ic);
3479           IC_LEFT (ic) = t;
3480           emitcode (";", "Swapped plus args.");
3481         }
3482
3483       /* if both left & right are in bit
3484          space */
3485       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3486           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3487         {
3488           genPlusBits (ic);
3489           goto release;
3490         }
3491
3492       /* if left in bit space & right literal */
3493       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3494           AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3495         {
3496           emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3497           /* if result in bit space */
3498           if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3499             {
3500               if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3501                 emitcode ("cpl", "c");
3502               outBitC (IC_RESULT (ic));
3503             }
3504           else
3505             {
3506               size = getDataSize (IC_RESULT (ic));
3507               _startLazyDPSEvaluation ();
3508               while (size--)
3509                 {
3510                   MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3511                   emitcode ("addc", "a,#00");
3512                   aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3513                 }
3514               _endLazyDPSEvaluation ();
3515             }
3516           goto release;
3517         }
3518
3519       /* if I can do an increment instead
3520          of add then GOOD for ME */
3521       if (genPlusIncr (ic) == TRUE)
3522         {
3523           emitcode (";", "did genPlusIncr");
3524           goto release;
3525         }
3526
3527     }
3528   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3529
3530   _startLazyDPSEvaluation ();
3531   while (size--)
3532     {
3533       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
3534         {
3535           MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3536           if (offset == 0)
3537             emitcode ("add", "a,%s",
3538                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3539           else
3540             emitcode ("addc", "a,%s",
3541                  aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3542         }
3543       else
3544         {
3545           if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
3546           {
3547               /* right is going to use ACC or we would have taken the
3548                * above branch.
3549                */
3550               assert(AOP_NEEDSACC(IC_RIGHT(ic)));
3551        TR_AP("#3");
3552               D(emitcode(";", "+ AOP_ACC special case."););
3553               emitcode("xch", "a, %s", DP2_RESULT_REG);
3554           }
3555           MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE));
3556           if (offset == 0)
3557           {
3558             if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
3559             {
3560          TR_AP("#4");
3561                 emitcode("add", "a, %s", DP2_RESULT_REG); 
3562             }
3563             else
3564             {
3565                 emitcode ("add", "a,%s",
3566                         aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE));
3567             }
3568           }
3569           else
3570           {
3571             emitcode ("addc", "a,%s",
3572                   aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE));
3573           }
3574         }
3575       if (!pushResult)
3576         {
3577           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3578         }
3579       else
3580         {
3581           emitcode ("push", "acc");
3582         }
3583       offset++;
3584     }
3585   _endLazyDPSEvaluation ();
3586
3587   if (pushResult)
3588     {
3589       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3590
3591       size = getDataSize (IC_LEFT (ic));
3592       rSize = getDataSize (IC_RESULT (ic));
3593
3594       ADJUST_PUSHED_RESULT(size, rSize);
3595
3596       _startLazyDPSEvaluation ();
3597       while (size--)
3598         {
3599           emitcode ("pop", "acc");
3600           aopPut (AOP (IC_RESULT (ic)), "a", size);
3601         }
3602       _endLazyDPSEvaluation ();
3603     }
3604
3605   adjustArithmeticResult (ic);
3606
3607 release:
3608   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3609   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3610   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3611 }
3612
3613 /*-----------------------------------------------------------------*/
3614 /* genMinusDec :- does subtraction with deccrement if possible     */
3615 /*-----------------------------------------------------------------*/
3616 static bool
3617 genMinusDec (iCode * ic)
3618 {
3619   unsigned int icount;
3620   unsigned int size = getDataSize (IC_RESULT (ic));
3621
3622   /* will try to generate an increment */
3623   /* if the right side is not a literal
3624      we cannot */
3625   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3626     return FALSE;
3627
3628   /* if the literal value of the right hand side
3629      is greater than 4 then it is not worth it */
3630   if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3631     return FALSE;
3632
3633   /* if decrement 16 bits in register */
3634   if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3635       AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3636       sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3637       (size > 1) &&
3638       (icount == 1))
3639     {
3640       symbol *tlbl;
3641       int emitTlbl;
3642       int labelRange;
3643
3644       /* If the next instruction is a goto and the goto target
3645          * is <= 5 instructions previous to this, we can generate
3646          * jumps straight to that target.
3647        */
3648       if (ic->next && ic->next->op == GOTO
3649           && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3650           && labelRange <= 5)
3651         {
3652           emitcode (";", "tail decrement optimized (range %d)", labelRange);
3653           tlbl = IC_LABEL (ic->next);
3654           emitTlbl = 0;
3655         }
3656       else
3657         {
3658           tlbl = newiTempLabel (NULL);
3659           emitTlbl = 1;
3660         }
3661
3662       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE));
3663       if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3664           AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3665           IS_AOP_PREG (IC_RESULT (ic)))
3666         emitcode ("cjne", "%s,#0xff,%05d$"
3667                   ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3668                   ,tlbl->key + 100);
3669       else
3670         {
3671           emitcode ("mov", "a,#0xff");
3672           emitcode ("cjne", "a,%s,%05d$"
3673                     ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)
3674                     ,tlbl->key + 100);
3675         }
3676       emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE));
3677       if (size > 2)
3678         {
3679           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3680               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3681               IS_AOP_PREG (IC_RESULT (ic)))
3682             emitcode ("cjne", "%s,#0xff,%05d$"
3683                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3684                       ,tlbl->key + 100);
3685           else
3686             {
3687               emitcode ("cjne", "a,%s,%05d$"
3688                   ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)
3689                         ,tlbl->key + 100);
3690             }
3691           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE));
3692         }
3693       if (size > 3)
3694         {
3695           if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3696               AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
3697               IS_AOP_PREG (IC_RESULT (ic)))
3698             emitcode ("cjne", "%s,#0xff,%05d$"
3699                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3700                       ,tlbl->key + 100);
3701           else
3702             {
3703               emitcode ("cjne", "a,%s,%05d$"
3704                   ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)
3705                         ,tlbl->key + 100);
3706             }
3707           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE));
3708         }
3709       if (emitTlbl)
3710         {
3711           emitcode ("", "%05d$:", tlbl->key + 100);
3712         }
3713       return TRUE;
3714     }
3715
3716   /* if the sizes are greater than 1 then we cannot */
3717   if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3718       AOP_SIZE (IC_LEFT (ic)) > 1)
3719     return FALSE;
3720
3721   /* we can if the aops of the left & result match or
3722      if they are in registers and the registers are the
3723      same */
3724   if (
3725        AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3726        AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3727        sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3728     {
3729
3730       _startLazyDPSEvaluation ();
3731       while (icount--)
3732         {
3733           emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
3734         }
3735       _endLazyDPSEvaluation ();
3736
3737       return TRUE;
3738     }
3739
3740   return FALSE;
3741 }
3742
3743 /*-----------------------------------------------------------------*/
3744 /* addSign - complete with sign                                    */
3745 /*-----------------------------------------------------------------*/
3746 static void
3747 addSign (operand * result, int offset, int sign)
3748 {
3749   int size = (getDataSize (result) - offset);
3750   if (size > 0)
3751     {
3752       _startLazyDPSEvaluation();
3753       if (sign)
3754         {
3755           emitcode ("rlc", "a");
3756           emitcode ("subb", "a,acc");
3757           while (size--)
3758           {
3759             aopPut (AOP (result), "a", offset++);
3760           }
3761         }
3762       else
3763       {
3764         while (size--)
3765         {
3766           aopPut (AOP (result), zero, offset++);
3767         }
3768       }
3769       _endLazyDPSEvaluation();
3770     }
3771 }
3772
3773 /*-----------------------------------------------------------------*/
3774 /* genMinusBits - generates code for subtraction  of two bits      */
3775 /*-----------------------------------------------------------------*/
3776 static void
3777 genMinusBits (iCode * ic)
3778 {
3779   symbol *lbl = newiTempLabel (NULL);
3780
3781   D (emitcode (";", "genMinusBits "););
3782
3783   if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3784     {
3785       emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3786       emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3787       emitcode ("cpl", "c");
3788       emitcode ("", "%05d$:", (lbl->key + 100));
3789       outBitC (IC_RESULT (ic));
3790     }
3791   else
3792     {
3793       emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3794       emitcode ("subb", "a,acc");
3795       emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3796       emitcode ("inc", "a");
3797       emitcode ("", "%05d$:", (lbl->key + 100));
3798       aopPut (AOP (IC_RESULT (ic)), "a", 0);
3799       addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3800     }
3801 }
3802
3803 /*-----------------------------------------------------------------*/
3804 /* genMinus - generates code for subtraction                       */
3805 /*-----------------------------------------------------------------*/
3806 static void
3807 genMinus (iCode * ic)
3808 {
3809   int size, offset = 0;
3810   int rSize;
3811   unsigned long lit = 0L;
3812   bool pushResult = FALSE;
3813
3814   D (emitcode (";", "genMinus "););
3815
3816   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
3817   aopOp (IC_RIGHT (ic), ic, FALSE, TRUE);
3818   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) &&
3819       (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2))
3820     {
3821       pushResult = TRUE;
3822     }
3823   else
3824     {
3825       aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR);
3826
3827       /* special cases :- */
3828       /* if both left & right are in bit space */
3829       if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3830           AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3831         {
3832           genMinusBits (ic);
3833           goto release;
3834         }
3835
3836       /* if I can do an decrement instead
3837          of subtract then GOOD for ME */
3838       if (genMinusDec (ic) == TRUE)
3839         goto release;
3840
3841     }
3842
3843   size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
3844
3845   if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3846     {
3847       CLRC;
3848     }
3849   else
3850     {
3851       lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3852       lit = -(long) lit;
3853     }
3854
3855
3856   /* if literal, add a,#-lit, else normal subb */
3857   _startLazyDPSEvaluation ();
3858   while (size--)
3859     {
3860       MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE));
3861       if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3862         emitcode ("subb", "a,%s",
3863                   aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE));
3864       else
3865         {
3866           /* first add without previous c */
3867           if (!offset) {
3868             if (!size && lit==-1) {
3869               emitcode ("dec", "a");
3870             } else {
3871               emitcode ("add", "a,#0x%02x",
3872                         (unsigned int) (lit & 0x0FFL));
3873             }
3874           } else {
3875             emitcode ("addc", "a,#0x%02x",
3876                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3877           }
3878         }
3879
3880       if (pushResult)
3881         {
3882           emitcode ("push", "acc");
3883         }
3884       else
3885         {
3886           aopPut (AOP (IC_RESULT (ic)), "a", offset);
3887         }
3888       offset++;
3889     }
3890   _endLazyDPSEvaluation ();
3891
3892   if (pushResult)
3893     {
3894       aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
3895
3896       size = getDataSize (IC_LEFT (ic));
3897       rSize = getDataSize (IC_RESULT (ic));
3898
3899       ADJUST_PUSHED_RESULT(size, rSize);
3900
3901       _startLazyDPSEvaluation ();
3902       while (size--)
3903         {
3904           emitcode ("pop", "acc");
3905           aopPut (AOP (IC_RESULT (ic)), "a", size);
3906         }
3907       _endLazyDPSEvaluation ();
3908     }
3909
3910   adjustArithmeticResult (ic);
3911
3912 release:
3913   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3914   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3915   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3916 }
3917
3918
3919 /*-----------------------------------------------------------------*/
3920 /* genMultbits :- multiplication of bits                           */
3921 /*-----------------------------------------------------------------*/
3922 static void
3923 genMultbits (operand * left,
3924              operand * right,
3925              operand * result,
3926              iCode   * ic)
3927 {
3928   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3929   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3930   aopOp(result, ic, TRUE, FALSE);
3931   outBitC (result);
3932 }
3933
3934
3935 /*-----------------------------------------------------------------*/
3936 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3937 /*-----------------------------------------------------------------*/
3938 static void
3939 genMultOneByte (operand * left,
3940                 operand * right,
3941                 operand * result,
3942                 iCode   * ic)
3943 {
3944   sym_link *opetype = operandType (result);
3945   symbol *lbl;
3946
3947
3948   /* (if two literals: the value is computed before) */
3949   /* if one literal, literal on the right */
3950   if (AOP_TYPE (left) == AOP_LIT)
3951     {
3952       operand *t = right;
3953       right = left;
3954       left = t;
3955       emitcode (";", "swapped left and right");
3956     }
3957
3958   if (SPEC_USIGN(opetype)
3959       // ignore the sign of left and right, what else can we do?
3960       || (SPEC_USIGN(operandType(left)) && 
3961           SPEC_USIGN(operandType(right)))) {
3962     // just an unsigned 8*8=8/16 multiply
3963     //emitcode (";","unsigned");
3964     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
3965     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3966     emitcode ("mul", "ab");
3967    
3968     _G.accInUse++;
3969     aopOp(result, ic, TRUE, FALSE);
3970       
3971       if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
3972       {
3973           // this should never happen
3974           fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3975                    AOP_SIZE(result), __FILE__, lineno);
3976           exit (1);
3977       }      
3978       
3979     aopPut (AOP (result), "a", 0);
3980     _G.accInUse--;
3981     if (AOP_SIZE(result)==2) 
3982     {
3983       aopPut (AOP (result), "b", 1);
3984     }
3985     return;
3986   }
3987
3988   // we have to do a signed multiply
3989
3990   emitcode (";", "signed");
3991   emitcode ("clr", "F0"); // reset sign flag
3992   MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
3993
3994   lbl=newiTempLabel(NULL);
3995   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
3996   // left side is negative, 8-bit two's complement, this fails for -128
3997   emitcode ("setb", "F0"); // set sign flag
3998   emitcode ("cpl", "a");
3999   emitcode ("inc", "a");
4000
4001   emitcode ("", "%05d$:", lbl->key+100);
4002
4003   /* if literal */
4004   if (AOP_TYPE(right)==AOP_LIT) {
4005     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
4006     /* AND literal negative */
4007     if ((int) val < 0) {
4008       emitcode ("cpl", "F0"); // complement sign flag
4009       emitcode ("mov", "b,#0x%02x", -val);
4010     } else {
4011       emitcode ("mov", "b,#0x%02x", val);
4012     }
4013   } else {
4014     lbl=newiTempLabel(NULL);
4015     emitcode ("mov", "b,a");
4016     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
4017     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
4018     // right side is negative, 8-bit two's complement
4019     emitcode ("cpl", "F0"); // complement sign flag
4020     emitcode ("cpl", "a");
4021     emitcode ("inc", "a");
4022     emitcode ("", "%05d$:", lbl->key+100);
4023   }
4024   emitcode ("mul", "ab");
4025     
4026   _G.accInUse++;
4027   aopOp(result, ic, TRUE, FALSE);
4028     
4029   if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
4030   {
4031     // this should never happen
4032       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
4033                AOP_SIZE(result), __FILE__, lineno);
4034       exit (1);
4035   }    
4036     
4037   lbl=newiTempLabel(NULL);
4038   emitcode ("jnb", "F0,%05d$", lbl->key+100);
4039   // only ONE op was negative, we have to do a 8/16-bit two's complement
4040   emitcode ("cpl", "a"); // lsb
4041   if (AOP_SIZE(result)==1) {
4042     emitcode ("inc", "a");
4043   } else {
4044     emitcode ("add", "a,#1");
4045     emitcode ("xch", "a,b");
4046     emitcode ("cpl", "a"); // msb
4047     emitcode ("addc", "a,#0");
4048     emitcode ("xch", "a,b");
4049   }
4050
4051   emitcode ("", "%05d$:", lbl->key+100);
4052   aopPut (AOP (result), "a", 0);
4053   _G.accInUse--;
4054   if (AOP_SIZE(result)==2) {
4055     aopPut (AOP (result), "b", 1);
4056   }
4057 }
4058
4059 /*-----------------------------------------------------------------*/
4060 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
4061 /*-----------------------------------------------------------------*/
4062 static void genMultTwoByte (operand *left, operand *right, 
4063                             operand *result, iCode *ic)
4064 {
4065         sym_link *retype = getSpec(operandType(right));
4066         sym_link *letype = getSpec(operandType(left));
4067         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4068         symbol *lbl;
4069
4070         if (AOP_TYPE (left) == AOP_LIT) {
4071                 operand *t = right;
4072                 right = left;
4073                 left = t;
4074         }
4075         /* load up MB with right */
4076         if (!umult) {
4077                 emitcode("clr","F0");
4078                 if (AOP_TYPE(right) == AOP_LIT) {
4079                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4080                         if (val < 0) {
4081                                 emitcode("setb","F0");
4082                                 val = -val;
4083                         } 
4084                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4085                         emitcode ("mov","mb,#0x%02x",val & 0xff);
4086                 } else {
4087                         lbl = newiTempLabel(NULL);
4088                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4089                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4090                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4091                         emitcode ("xch", "a,b");
4092                         emitcode ("cpl","a");
4093                         emitcode ("add", "a,#1");
4094                         emitcode ("xch", "a,b");
4095                         emitcode ("cpl", "a"); // msb
4096                         emitcode ("addc", "a,#0");
4097                         emitcode ("setb","F0");
4098                         emitcode ("","%05d$:",lbl->key+100);
4099                         emitcode ("mov","mb,b");
4100                         emitcode ("mov","mb,a");
4101                 }
4102         } else {
4103                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4104                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4105         }
4106         /* load up MA with left */
4107         if (!umult) {
4108                 lbl = newiTempLabel(NULL);
4109                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4110                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4111                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4112                 emitcode ("xch", "a,b");
4113                 emitcode ("cpl","a");
4114                 emitcode ("add", "a,#1");
4115                 emitcode ("xch", "a,b");
4116                 emitcode ("cpl", "a"); // msb
4117                 emitcode ("addc","a,#0");
4118                 emitcode ("jbc","F0,%05d$",lbl->key+100);
4119                 emitcode ("setb","F0");
4120                 emitcode ("","%05d$:",lbl->key+100);
4121                 emitcode ("mov","ma,b");
4122                 emitcode ("mov","ma,a");
4123         } else {
4124                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4125                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4126         }
4127         /* wait for multiplication to finish */
4128         lbl = newiTempLabel(NULL);
4129         emitcode("","%05d$:", lbl->key+100);
4130         emitcode("mov","a,mcnt1");
4131         emitcode("anl","a,#0x80");
4132         emitcode("jnz","%05d$",lbl->key+100);
4133         
4134         freeAsmop (left, NULL, ic, TRUE);
4135         freeAsmop (right, NULL, ic,TRUE);
4136         aopOp(result, ic, TRUE, FALSE);
4137
4138         /* if unsigned then simple */   
4139         if (umult) {
4140                 emitcode ("mov","a,ma");
4141                 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4142                 emitcode ("mov","a,ma");
4143                 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4144                 aopPut(AOP(result),"ma",1);
4145                 aopPut(AOP(result),"ma",0);
4146         } else {
4147                 emitcode("push","ma");
4148                 emitcode("push","ma");
4149                 emitcode("push","ma");
4150                 MOVA("ma");
4151                 /* negate result if needed */
4152                 lbl = newiTempLabel(NULL);      
4153                 emitcode("jnb","F0,%05d$",lbl->key+100);
4154                 emitcode("cpl","a");
4155                 emitcode("add","a,#1");
4156                 emitcode("","%05d$:", lbl->key+100);
4157                 aopPut(AOP(result),"a",0);
4158                 emitcode("pop","acc");
4159                 lbl = newiTempLabel(NULL);      
4160                 emitcode("jnb","F0,%05d$",lbl->key+100);
4161                 emitcode("cpl","a");
4162                 emitcode("addc","a,#0");
4163                 emitcode("","%05d$:", lbl->key+100);
4164                 aopPut(AOP(result),"a",1);
4165                 emitcode("pop","acc");
4166                 if (AOP_SIZE(result) >= 3) {
4167                         lbl = newiTempLabel(NULL);      
4168                         emitcode("jnb","F0,%05d$",lbl->key+100);
4169                         emitcode("cpl","a");
4170                         emitcode("addc","a,#0");                        
4171                         emitcode("","%05d$:", lbl->key+100);
4172                         aopPut(AOP(result),"a",2);
4173                 }
4174                 emitcode("pop","acc");
4175                 if (AOP_SIZE(result) >= 4) {
4176                         lbl = newiTempLabel(NULL);      
4177                         emitcode("jnb","F0,%05d$",lbl->key+100);
4178                         emitcode("cpl","a");
4179                         emitcode("addc","a,#0");                        
4180                         emitcode("","%05d$:", lbl->key+100);
4181                         aopPut(AOP(result),"a",3);
4182                 }
4183                 
4184         }
4185         freeAsmop (result, NULL, ic, TRUE);
4186         return ;
4187 }
4188
4189 /*-----------------------------------------------------------------*/
4190 /* genMult - generates code for multiplication                     */
4191 /*-----------------------------------------------------------------*/
4192 static void
4193 genMult (iCode * ic)
4194 {
4195   operand *left = IC_LEFT (ic);
4196   operand *right = IC_RIGHT (ic);
4197   operand *result = IC_RESULT (ic);
4198
4199   D (emitcode (";", "genMult "););
4200
4201   /* assign the amsops */
4202   AOP_OP_2 (ic);
4203
4204   /* special cases first */
4205   /* both are bits */
4206   if (AOP_TYPE (left) == AOP_CRY &&
4207       AOP_TYPE (right) == AOP_CRY)
4208     {
4209       genMultbits (left, right, result, ic);
4210       goto release;
4211     }
4212
4213   /* if both are of size == 1 */
4214   if (AOP_SIZE (left) == 1 &&
4215       AOP_SIZE (right) == 1)
4216     {
4217       genMultOneByte (left, right, result, ic);
4218       goto release;
4219     }
4220
4221   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4222           /* use the ds390 ARITHMETIC accel UNIT */
4223           genMultTwoByte (left, right, result, ic);
4224           return ;
4225   }
4226   /* should have been converted to function call */
4227   assert (0);
4228
4229 release:
4230   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4231   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4232   freeAsmop (result, NULL, ic, TRUE);
4233 }
4234
4235 /*-----------------------------------------------------------------*/
4236 /* genDivbits :- division of bits                                  */
4237 /*-----------------------------------------------------------------*/
4238 static void
4239 genDivbits (operand * left,
4240             operand * right,
4241             operand * result,
4242             iCode   * ic)
4243 {
4244
4245   char *l;
4246
4247   /* the result must be bit */
4248   LOAD_AB_FOR_DIV (left, right, l);
4249   emitcode ("div", "ab");
4250   emitcode ("rrc", "a");
4251   aopOp(result, ic, TRUE, FALSE);
4252     
4253   aopPut (AOP (result), "c", 0);
4254 }
4255
4256 /*-----------------------------------------------------------------*/
4257 /* genDivOneByte : 8 bit division                                  */
4258 /*-----------------------------------------------------------------*/
4259 static void
4260 genDivOneByte (operand * left,
4261                operand * right,
4262                operand * result,
4263                iCode   * ic)
4264 {
4265   sym_link *opetype = operandType (result);
4266   char *l;
4267   symbol *lbl;
4268   int size, offset;
4269
4270   offset = 1;
4271   /* signed or unsigned */
4272   if (SPEC_USIGN (opetype))
4273     {
4274         /* unsigned is easy */
4275         LOAD_AB_FOR_DIV (left, right, l);
4276         emitcode ("div", "ab");
4277
4278         _G.accInUse++;
4279         aopOp(result, ic, TRUE, FALSE);
4280         aopPut (AOP (result), "a", 0);
4281         _G.accInUse--;
4282
4283         size = AOP_SIZE (result) - 1;
4284         
4285         while (size--)
4286         {
4287             aopPut (AOP (result), zero, offset++);
4288         }
4289       return;
4290     }
4291
4292   /* signed is a little bit more difficult */
4293
4294   /* save the signs of the operands */
4295   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4296   MOVA (l);
4297   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4298   emitcode ("push", "acc");     /* save it on the stack */
4299
4300   /* now sign adjust for both left & right */
4301   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4302   MOVA (l);
4303   lbl = newiTempLabel (NULL);
4304   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4305   emitcode ("cpl", "a");
4306   emitcode ("inc", "a");
4307   emitcode ("", "%05d$:", (lbl->key + 100));
4308   emitcode ("mov", "b,a");
4309
4310   /* sign adjust left side */
4311   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4312   MOVA (l);
4313
4314   lbl = newiTempLabel (NULL);
4315   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4316   emitcode ("cpl", "a");
4317   emitcode ("inc", "a");
4318   emitcode ("", "%05d$:", (lbl->key + 100));
4319
4320   /* now the division */
4321   emitcode ("nop", "; workaround for DS80C390 div bug.");
4322   emitcode ("div", "ab");
4323   /* we are interested in the lower order
4324      only */
4325   emitcode ("mov", "b,a");
4326   lbl = newiTempLabel (NULL);
4327   emitcode ("pop", "acc");
4328   /* if there was an over flow we don't
4329      adjust the sign of the result */
4330   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4331   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4332   CLRC;
4333   emitcode ("clr", "a");
4334   emitcode ("subb", "a,b");
4335   emitcode ("mov", "b,a");
4336   emitcode ("", "%05d$:", (lbl->key + 100));
4337
4338   /* now we are done */
4339     _G.accInUse++;
4340     aopOp(result, ic, TRUE, FALSE);
4341     
4342     aopPut (AOP (result), "b", 0);
4343     
4344     size = AOP_SIZE (result) - 1;
4345     
4346     if (size > 0)
4347     {
4348       emitcode ("mov", "c,b.7");
4349       emitcode ("subb", "a,acc");
4350     }
4351     while (size--)
4352     {
4353         aopPut (AOP (result), "a", offset++);
4354     }
4355     _G.accInUse--;
4356
4357 }
4358
4359 /*-----------------------------------------------------------------*/
4360 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
4361 /*-----------------------------------------------------------------*/
4362 static void genDivTwoByte (operand *left, operand *right, 
4363                             operand *result, iCode *ic)
4364 {
4365         sym_link *retype = getSpec(operandType(right));
4366         sym_link *letype = getSpec(operandType(left));
4367         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4368         symbol *lbl;
4369
4370         /* load up MA with left */
4371         if (!umult) {
4372                 emitcode("clr","F0");
4373                 lbl = newiTempLabel(NULL);
4374                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4375                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4376                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4377                 emitcode ("xch", "a,b");
4378                 emitcode ("cpl","a");
4379                 emitcode ("add", "a,#1");
4380                 emitcode ("xch", "a,b");
4381                 emitcode ("cpl", "a"); // msb
4382                 emitcode ("addc","a,#0");
4383                 emitcode ("setb","F0");
4384                 emitcode ("","%05d$:",lbl->key+100);
4385                 emitcode ("mov","ma,b");
4386                 emitcode ("mov","ma,a");
4387         } else {
4388                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4389                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4390         }
4391
4392         /* load up MB with right */
4393         if (!umult) {
4394                 if (AOP_TYPE(right) == AOP_LIT) {
4395                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4396                         if (val < 0) {
4397                                 lbl = newiTempLabel(NULL);
4398                                 emitcode ("jbc","F0,%05d$",lbl->key+100);
4399                                 emitcode("setb","F0");
4400                                 emitcode ("","%05d$:",lbl->key+100);
4401                                 val = -val;
4402                         } 
4403                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4404                         emitcode ("mov","mb,#0x%02x",val & 0xff);
4405                 } else {
4406                         lbl = newiTempLabel(NULL);
4407                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4408                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4409                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4410                         emitcode ("xch", "a,b");
4411                         emitcode ("cpl","a");
4412                         emitcode ("add", "a,#1");
4413                         emitcode ("xch", "a,b");
4414                         emitcode ("cpl", "a"); // msb
4415                         emitcode ("addc", "a,#0");
4416                         emitcode ("jbc","F0,%05d$",lbl->key+100);
4417                         emitcode ("setb","F0");
4418                         emitcode ("","%05d$:",lbl->key+100);
4419                         emitcode ("mov","mb,b");
4420                         emitcode ("mov","mb,a");
4421                 }
4422         } else {
4423                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4424                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4425         }
4426
4427         /* wait for multiplication to finish */
4428         lbl = newiTempLabel(NULL);
4429         emitcode("","%05d$:", lbl->key+100);
4430         emitcode("mov","a,mcnt1");
4431         emitcode("anl","a,#0x80");
4432         emitcode("jnz","%05d$",lbl->key+100);
4433         
4434         freeAsmop (left, NULL, ic, TRUE);
4435         freeAsmop (right, NULL, ic,TRUE);
4436         aopOp(result, ic, TRUE, FALSE);
4437
4438         /* if unsigned then simple */   
4439         if (umult) {
4440                 aopPut(AOP(result),"ma",1);
4441                 aopPut(AOP(result),"ma",0);
4442         } else {
4443                 emitcode("push","ma");
4444                 MOVA("ma");
4445                 /* negate result if needed */
4446                 lbl = newiTempLabel(NULL);      
4447                 emitcode("jnb","F0,%05d$",lbl->key+100);
4448                 emitcode("cpl","a");
4449                 emitcode("add","a,#1");
4450                 emitcode("","%05d$:", lbl->key+100);
4451                 aopPut(AOP(result),"a",0);
4452                 emitcode("pop","acc");
4453                 lbl = newiTempLabel(NULL);      
4454                 emitcode("jnb","F0,%05d$",lbl->key+100);
4455                 emitcode("cpl","a");
4456                 emitcode("addc","a,#0");
4457                 emitcode("","%05d$:", lbl->key+100);
4458                 aopPut(AOP(result),"a",1);
4459         }
4460         freeAsmop (result, NULL, ic, TRUE);
4461         return ;
4462 }
4463
4464 /*-----------------------------------------------------------------*/
4465 /* genDiv - generates code for division                            */
4466 /*-----------------------------------------------------------------*/
4467 static void
4468 genDiv (iCode * ic)
4469 {
4470   operand *left = IC_LEFT (ic);
4471   operand *right = IC_RIGHT (ic);
4472   operand *result = IC_RESULT (ic);
4473
4474   D (emitcode (";", "genDiv "););
4475
4476   /* assign the amsops */
4477   AOP_OP_2 (ic);
4478
4479   /* special cases first */
4480   /* both are bits */
4481   if (AOP_TYPE (left) == AOP_CRY &&
4482       AOP_TYPE (right) == AOP_CRY)
4483     {
4484       genDivbits (left, right, result, ic);
4485       goto release;
4486     }
4487
4488   /* if both are of size == 1 */
4489   if (AOP_SIZE (left) == 1 &&
4490       AOP_SIZE (right) == 1)
4491     {
4492       genDivOneByte (left, right, result, ic);
4493       goto release;
4494     }
4495
4496   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4497           /* use the ds390 ARITHMETIC accel UNIT */
4498           genDivTwoByte (left, right, result, ic);
4499           return ;
4500   }
4501   /* should have been converted to function call */
4502   assert (0);
4503 release:
4504   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4505   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4506   freeAsmop (result, NULL, ic, TRUE);
4507 }
4508
4509 /*-----------------------------------------------------------------*/
4510 /* genModbits :- modulus of bits                                   */
4511 /*-----------------------------------------------------------------*/
4512 static void
4513 genModbits (operand * left,
4514             operand * right,
4515             operand * result,
4516             iCode   * ic)
4517 {
4518
4519   char *l;
4520
4521   /* the result must be bit */
4522   LOAD_AB_FOR_DIV (left, right, l);
4523   emitcode ("div", "ab");
4524   emitcode ("mov", "a,b");
4525   emitcode ("rrc", "a");
4526   aopOp(result, ic, TRUE, FALSE);
4527   aopPut (AOP (result), "c", 0);
4528 }
4529
4530 /*-----------------------------------------------------------------*/
4531 /* genModOneByte : 8 bit modulus                                   */
4532 /*-----------------------------------------------------------------*/
4533 static void
4534 genModOneByte (operand * left,
4535                operand * right,
4536                operand * result,
4537                iCode   * ic)
4538 {
4539   sym_link *opetype = operandType (result);
4540   char *l;
4541   symbol *lbl;
4542
4543   /* signed or unsigned */
4544   if (SPEC_USIGN (opetype))
4545     {
4546       /* unsigned is easy */
4547       LOAD_AB_FOR_DIV (left, right, l);
4548       emitcode ("div", "ab");
4549       aopOp(result, ic, TRUE, FALSE);   
4550       aopPut (AOP (result), "b", 0);
4551       return;
4552     }
4553
4554   /* signed is a little bit more difficult */
4555
4556   /* save the signs of the operands */
4557   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4558   MOVA (l);
4559
4560   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
4561   emitcode ("push", "acc");     /* save it on the stack */
4562
4563   /* now sign adjust for both left & right */
4564   l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE);
4565   MOVA (l);
4566
4567   lbl = newiTempLabel (NULL);
4568   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4569   emitcode ("cpl", "a");
4570   emitcode ("inc", "a");
4571   emitcode ("", "%05d$:", (lbl->key + 100));
4572   emitcode ("mov", "b,a");
4573
4574   /* sign adjust left side */
4575   l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
4576   MOVA (l);
4577
4578   lbl = newiTempLabel (NULL);
4579   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4580   emitcode ("cpl", "a");
4581   emitcode ("inc", "a");
4582   emitcode ("", "%05d$:", (lbl->key + 100));
4583
4584   /* now the multiplication */
4585   emitcode ("nop", "; workaround for DS80C390 div bug.");
4586   emitcode ("div", "ab");
4587   /* we are interested in the lower order
4588      only */
4589   lbl = newiTempLabel (NULL);
4590   emitcode ("pop", "acc");
4591   /* if there was an over flow we don't
4592      adjust the sign of the result */
4593   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4594   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4595   CLRC;
4596   emitcode ("clr", "a");
4597   emitcode ("subb", "a,b");
4598   emitcode ("mov", "b,a");
4599   emitcode ("", "%05d$:", (lbl->key + 100));
4600
4601   /* now we are done */
4602   aopOp(result, ic, TRUE, FALSE);    
4603   aopPut (AOP (result), "b", 0);
4604
4605 }
4606
4607 /*-----------------------------------------------------------------*/
4608 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
4609 /*-----------------------------------------------------------------*/
4610 static void genModTwoByte (operand *left, operand *right, 
4611                             operand *result, iCode *ic)
4612 {
4613         sym_link *retype = getSpec(operandType(right));
4614         sym_link *letype = getSpec(operandType(left));
4615         int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4616         symbol *lbl;
4617
4618         /* load up MA with left */
4619         if (!umult) {
4620                 lbl = newiTempLabel(NULL);
4621                 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4622                 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4623                 emitcode ("jnb","acc.7,%05d$",lbl->key+100);
4624                 emitcode ("xch", "a,b");
4625                 emitcode ("cpl","a");
4626                 emitcode ("add", "a,#1");
4627                 emitcode ("xch", "a,b");
4628                 emitcode ("cpl", "a"); // msb
4629                 emitcode ("addc","a,#0");
4630                 emitcode ("","%05d$:",lbl->key+100);
4631                 emitcode ("mov","ma,b");
4632                 emitcode ("mov","ma,a");
4633         } else {
4634                 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
4635                 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
4636         }
4637
4638         /* load up MB with right */
4639         if (!umult) {
4640                 if (AOP_TYPE(right) == AOP_LIT) {
4641                         int val=floatFromVal (AOP (right)->aopu.aop_lit);
4642                         if (val < 0) {
4643                                 val = -val;
4644                         } 
4645                         emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
4646                         emitcode ("mov","mb,#0x%02x",val & 0xff);
4647                 } else {
4648                         lbl = newiTempLabel(NULL);
4649                         emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4650                         emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4651                         emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
4652                         emitcode ("xch", "a,b");
4653                         emitcode ("cpl","a");
4654                         emitcode ("add", "a,#1");
4655                         emitcode ("xch", "a,b");
4656                         emitcode ("cpl", "a"); // msb
4657                         emitcode ("addc", "a,#0");
4658                         emitcode ("","%05d$:",lbl->key+100);
4659                         emitcode ("mov","mb,b");
4660                         emitcode ("mov","mb,a");
4661                 }
4662         } else {
4663                 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
4664                 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
4665         }
4666
4667         /* wait for multiplication to finish */
4668         lbl = newiTempLabel(NULL);
4669         emitcode("","%05d$:", lbl->key+100);
4670         emitcode("mov","a,mcnt1");
4671         emitcode("anl","a,#0x80");
4672         emitcode("jnz","%05d$",lbl->key+100);
4673         
4674         freeAsmop (left, NULL, ic, TRUE);
4675         freeAsmop (right, NULL, ic,TRUE);
4676         aopOp(result, ic, TRUE, FALSE);
4677
4678         aopPut(AOP(result),"mb",1);
4679         aopPut(AOP(result),"mb",0);
4680         freeAsmop (result, NULL, ic, TRUE);
4681         return ;
4682 }
4683
4684 /*-----------------------------------------------------------------*/
4685 /* genMod - generates code for division                            */
4686 /*-----------------------------------------------------------------*/
4687 static void
4688 genMod (iCode * ic)
4689 {
4690   operand *left = IC_LEFT (ic);
4691   operand *right = IC_RIGHT (ic);
4692   operand *result = IC_RESULT (ic);
4693
4694   D (emitcode (";", "genMod "); );
4695
4696   /* assign the amsops */
4697   AOP_OP_2 (ic);
4698
4699   /* special cases first */
4700   /* both are bits */
4701   if (AOP_TYPE (left) == AOP_CRY &&
4702       AOP_TYPE (right) == AOP_CRY)
4703     {
4704       genModbits (left, right, result, ic);
4705       goto release;
4706     }
4707
4708   /* if both are of size == 1 */
4709   if (AOP_SIZE (left) == 1 &&
4710       AOP_SIZE (right) == 1)
4711     {
4712       genModOneByte (left, right, result, ic);
4713       goto release;
4714     }
4715
4716   if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4717           /* use the ds390 ARITHMETIC accel UNIT */
4718           genModTwoByte (left, right, result, ic);
4719           return ;
4720   }
4721
4722   /* should have been converted to function call */
4723   assert (0);
4724
4725 release:
4726   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4727   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4728   freeAsmop (result, NULL, ic, TRUE);
4729 }
4730
4731 /*-----------------------------------------------------------------*/
4732 /* genIfxJump :- will create a jump depending on the ifx           */
4733 /*-----------------------------------------------------------------*/
4734 static void
4735 genIfxJump (iCode * ic, char *jval)
4736 {
4737   symbol *jlbl;
4738   symbol *tlbl = newiTempLabel (NULL);
4739   char *inst;
4740
4741   D (emitcode (";", "genIfxJump ");
4742     );
4743
4744   /* if true label then we jump if condition
4745      supplied is true */
4746   if (IC_TRUE (ic))
4747     {
4748       jlbl = IC_TRUE (ic);
4749       inst = ((strcmp (jval, "a") == 0 ? "jz" :
4750                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4751     }
4752   else
4753     {
4754       /* false label is present */
4755       jlbl = IC_FALSE (ic);
4756       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4757                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4758     }
4759   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4760     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4761   else
4762     emitcode (inst, "%05d$", tlbl->key + 100);
4763   emitcode ("ljmp", "%05d$", jlbl->key + 100);
4764   emitcode ("", "%05d$:", tlbl->key + 100);
4765
4766   /* mark the icode as generated */
4767   ic->generated = 1;
4768 }
4769
4770 /*-----------------------------------------------------------------*/
4771 /* genCmp :- greater or less than comparison                       */
4772 /*-----------------------------------------------------------------*/
4773 static void
4774 genCmp (operand * left, operand * right,
4775         iCode * ic, iCode * ifx, int sign)
4776 {
4777   int size, offset = 0;
4778   unsigned long lit = 0L;
4779   operand *result;
4780
4781   D (emitcode (";", "genCmp");
4782     );
4783
4784   result = IC_RESULT (ic);
4785
4786   /* if left & right are bit variables */
4787   if (AOP_TYPE (left) == AOP_CRY &&
4788       AOP_TYPE (right) == AOP_CRY)
4789     {
4790       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4791       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4792     }
4793   else
4794     {
4795       /* subtract right from left if at the
4796          end the carry flag is set then we know that
4797          left is greater than right */
4798       size = max (AOP_SIZE (left), AOP_SIZE (right));
4799
4800       /* if unsigned char cmp with lit, do cjne left,#right,zz */
4801       if ((size == 1) && !sign &&
4802           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4803         {
4804           symbol *lbl = newiTempLabel (NULL);
4805           emitcode ("cjne", "%s,%s,%05d$",
4806                     aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
4807                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
4808                     lbl->key + 100);
4809           emitcode ("", "%05d$:", lbl->key + 100);
4810         }
4811       else
4812         {
4813           if (AOP_TYPE (right) == AOP_LIT)
4814             {
4815               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4816               /* optimize if(x < 0) or if(x >= 0) */
4817               if (lit == 0L)
4818                 {
4819                   if (!sign)
4820                     {
4821                       CLRC;
4822                     }
4823                   else
4824                     {
4825                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
4826
4827                       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4828                       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4829
4830                       aopOp (result, ic, FALSE, FALSE);
4831
4832                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4833                         {
4834                           freeAsmop (result, NULL, ic, TRUE);
4835                           genIfxJump (ifx, "acc.7");
4836                           return;
4837                         }
4838                       else
4839                         {
4840                           emitcode ("rlc", "a");
4841                         }
4842                       goto release_freedLR;
4843                     }
4844                   goto release;
4845                 }
4846             }
4847           CLRC;
4848           while (size--)
4849             {
4850               emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
4851               MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
4852               emitcode (";", "genCmp #2");
4853               if (sign && (size == 0))
4854                 {
4855                   emitcode (";", "genCmp #3");
4856                   emitcode ("xrl", "a,#0x80");
4857                   if (AOP_TYPE (right) == AOP_LIT)
4858                     {
4859                       unsigned long lit = (unsigned long)
4860                       floatFromVal (AOP (right)->aopu.aop_lit);
4861                       emitcode (";", "genCmp #3.1");
4862                       emitcode ("subb", "a,#0x%02x",
4863                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4864                     }
4865                   else
4866                     {
4867                       emitcode (";", "genCmp #3.2");
4868                       if (AOP_NEEDSACC (right))
4869                         {
4870                           emitcode ("push", "acc");
4871                         }
4872                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++,
4873                                                        FALSE, FALSE, FALSE));
4874                       emitcode ("xrl", "b,#0x80");
4875                       if (AOP_NEEDSACC (right))
4876                         {
4877                           emitcode ("pop", "acc");
4878                         }
4879                       emitcode ("subb", "a,b");
4880                     }
4881                 }
4882               else
4883                 {
4884                   const char *s;
4885
4886                   emitcode (";", "genCmp #4");
4887                   if (AOP_NEEDSACC (right))
4888                     {
4889                       /* Yuck!! */
4890                       emitcode (";", "genCmp #4.1");
4891                       emitcode ("xch", "a, b");
4892                       MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE));
4893                       emitcode ("xch", "a, b");
4894                       s = "b";
4895                     }
4896                   else
4897                     {
4898                       emitcode (";", "genCmp #4.2");
4899                       s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE);
4900                     }
4901
4902                   emitcode ("subb", "a,%s", s);
4903                 }
4904             }
4905         }
4906     }
4907
4908 release:
4909 /* Don't need the left & right operands any more; do need the result. */
4910   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4911   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4912
4913   aopOp (result, ic, FALSE, FALSE);
4914
4915 release_freedLR:
4916
4917   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4918     {
4919       outBitC (result);
4920     }
4921   else
4922     {
4923       /* if the result is used in the next
4924          ifx conditional branch then generate
4925          code a little differently */
4926       if (ifx)
4927         {
4928           genIfxJump (ifx, "c");
4929         }
4930       else
4931         {
4932           outBitC (result);
4933         }
4934       /* leave the result in acc */
4935     }
4936   freeAsmop (result, NULL, ic, TRUE);
4937 }
4938
4939 /*-----------------------------------------------------------------*/
4940 /* genCmpGt :- greater than comparison                             */
4941 /*-----------------------------------------------------------------*/
4942 static void
4943 genCmpGt (iCode * ic, iCode * ifx)
4944 {
4945   operand *left, *right;
4946   sym_link *letype, *retype;
4947   int sign;
4948
4949   D (emitcode (";", "genCmpGt ");
4950     );
4951
4952   left = IC_LEFT (ic);
4953   right = IC_RIGHT (ic);
4954
4955   letype = getSpec (operandType (left));
4956   retype = getSpec (operandType (right));
4957   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4958
4959   /* assign the left & right amsops */
4960   AOP_OP_2 (ic);
4961
4962   genCmp (right, left, ic, ifx, sign);
4963 }
4964
4965 /*-----------------------------------------------------------------*/
4966 /* genCmpLt - less than comparisons                                */
4967 /*-----------------------------------------------------------------*/
4968 static void
4969 genCmpLt (iCode * ic, iCode * ifx)
4970 {
4971   operand *left, *right;
4972   sym_link *letype, *retype;
4973   int sign;
4974
4975   D (emitcode (";", "genCmpLt "););
4976
4977   left = IC_LEFT (ic);
4978   right = IC_RIGHT (ic);
4979
4980   letype = getSpec (operandType (left));
4981   retype = getSpec (operandType (right));
4982   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4983
4984   /* assign the left & right amsops */
4985   AOP_OP_2 (ic);
4986
4987   genCmp (left, right, ic, ifx, sign);
4988 }
4989
4990 /*-----------------------------------------------------------------*/
4991 /* gencjneshort - compare and jump if not equal                    */
4992 /*-----------------------------------------------------------------*/
4993 static void
4994 gencjneshort (operand * left, operand * right, symbol * lbl)
4995 {
4996   int size = max (AOP_SIZE (left), AOP_SIZE (right));
4997   int offset = 0;
4998   unsigned long lit = 0L;
4999
5000   D (emitcode (";", "gencjneshort");
5001     );
5002
5003   /* if the left side is a literal or
5004      if the right is in a pointer register and left
5005      is not */
5006   if ((AOP_TYPE (left) == AOP_LIT) ||
5007       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5008     {
5009       operand *t = right;
5010       right = left;
5011       left = t;
5012     }
5013
5014   if (AOP_TYPE (right) == AOP_LIT)
5015     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5016
5017   if (opIsGptr (left) || opIsGptr (right))
5018     {
5019       /* We are comparing a generic pointer to something.
5020        * Exclude the generic type byte from the comparison.
5021        */
5022       size--;
5023       D (emitcode (";", "cjneshort: generic ptr special case.");
5024         )
5025     }
5026
5027
5028   /* if the right side is a literal then anything goes */
5029   if (AOP_TYPE (right) == AOP_LIT &&
5030       AOP_TYPE (left) != AOP_DIR)
5031     {
5032       while (size--)
5033         {
5034           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5035           MOVA (l);
5036           emitcode ("cjne", "a,%s,%05d$",
5037                     aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
5038                     lbl->key + 100);
5039           offset++;
5040         }
5041     }
5042
5043   /* if the right side is in a register or in direct space or
5044      if the left is a pointer register & right is not */
5045   else if (AOP_TYPE (right) == AOP_REG ||
5046            AOP_TYPE (right) == AOP_DIR ||
5047            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5048            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5049     {
5050       while (size--)
5051         {
5052           MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5053           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5054               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5055             emitcode ("jnz", "%05d$", lbl->key + 100);
5056           else
5057             emitcode ("cjne", "a,%s,%05d$",
5058                       aopGet (AOP (right), offset, FALSE, TRUE, FALSE),
5059                       lbl->key + 100);
5060           offset++;
5061         }
5062     }
5063   else
5064     {
5065       /* right is a pointer reg need both a & b */
5066       while (size--)
5067         {
5068           char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
5069           if (strcmp (l, "b"))
5070             emitcode ("mov", "b,%s", l);
5071           MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5072           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5073           offset++;
5074         }
5075     }
5076 }
5077
5078 /*-----------------------------------------------------------------*/
5079 /* gencjne - compare and jump if not equal                         */
5080 /*-----------------------------------------------------------------*/
5081 static void
5082 gencjne (operand * left, operand * right, symbol * lbl)
5083 {
5084   symbol *tlbl = newiTempLabel (NULL);
5085
5086   D (emitcode (";", "gencjne");
5087     );
5088
5089   gencjneshort (left, right, lbl);
5090
5091   emitcode ("mov", "a,%s", one);
5092   emitcode ("sjmp", "%05d$", tlbl->key + 100);
5093   emitcode ("", "%05d$:", lbl->key + 100);
5094   emitcode ("clr", "a");
5095   emitcode ("", "%05d$:", tlbl->key + 100);
5096 }
5097
5098 /*-----------------------------------------------------------------*/
5099 /* genCmpEq - generates code for equal to                          */
5100 /*-----------------------------------------------------------------*/
5101 static void
5102 genCmpEq (iCode * ic, iCode * ifx)
5103 {
5104   operand *left, *right, *result;
5105
5106   D (emitcode (";", "genCmpEq ");
5107     );
5108
5109   AOP_OP_2 (ic);
5110   AOP_SET_LOCALS (ic);
5111
5112   /* if literal, literal on the right or
5113      if the right is in a pointer register and left
5114      is not */
5115   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5116       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5117     {
5118       operand *t = IC_RIGHT (ic);
5119       IC_RIGHT (ic) = IC_LEFT (ic);
5120       IC_LEFT (ic) = t;
5121     }
5122
5123   if (ifx &&                    /* !AOP_SIZE(result) */
5124       OP_SYMBOL (result) &&
5125       OP_SYMBOL (result)->regType == REG_CND)
5126     {
5127       symbol *tlbl;
5128       /* if they are both bit variables */
5129       if (AOP_TYPE (left) == AOP_CRY &&
5130           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5131         {
5132           if (AOP_TYPE (right) == AOP_LIT)
5133             {
5134               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5135               if (lit == 0L)
5136                 {
5137                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5138                   emitcode ("cpl", "c");
5139                 }
5140               else if (lit == 1L)
5141                 {
5142                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5143                 }
5144               else
5145                 {
5146                   emitcode ("clr", "c");
5147                 }
5148               /* AOP_TYPE(right) == AOP_CRY */
5149             }
5150           else
5151             {
5152               symbol *lbl = newiTempLabel (NULL);
5153               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5154               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5155               emitcode ("cpl", "c");
5156               emitcode ("", "%05d$:", (lbl->key + 100));
5157             }
5158           /* if true label then we jump if condition
5159              supplied is true */
5160           tlbl = newiTempLabel (NULL);
5161           if (IC_TRUE (ifx))
5162             {
5163               emitcode ("jnc", "%05d$", tlbl->key + 100);
5164               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5165             }
5166           else
5167             {
5168               emitcode ("jc", "%05d$", tlbl->key + 100);
5169               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5170             }
5171           emitcode ("", "%05d$:", tlbl->key + 100);
5172         }
5173       else
5174         {
5175           tlbl = newiTempLabel (NULL);
5176           gencjneshort (left, right, tlbl);
5177           if (IC_TRUE (ifx))
5178             {
5179               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5180               emitcode ("", "%05d$:", tlbl->key + 100);
5181             }
5182           else
5183             {
5184               symbol *lbl = newiTempLabel (NULL);
5185               emitcode ("sjmp", "%05d$", lbl->key + 100);
5186               emitcode ("", "%05d$:", tlbl->key + 100);
5187               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5188               emitcode ("", "%05d$:", lbl->key + 100);
5189             }
5190         }
5191       /* mark the icode as generated */
5192       ifx->generated = 1;
5193
5194       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5195       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5196       return;
5197     }
5198
5199   /* if they are both bit variables */
5200   if (AOP_TYPE (left) == AOP_CRY &&
5201       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5202     {
5203       if (AOP_TYPE (right) == AOP_LIT)
5204         {
5205           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5206           if (lit == 0L)
5207             {
5208               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5209               emitcode ("cpl", "c");
5210             }
5211           else if (lit == 1L)
5212             {
5213               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5214             }
5215           else
5216             {
5217               emitcode ("clr", "c");
5218             }
5219           /* AOP_TYPE(right) == AOP_CRY */
5220         }
5221       else
5222         {
5223           symbol *lbl = newiTempLabel (NULL);
5224           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5225           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5226           emitcode ("cpl", "c");
5227           emitcode ("", "%05d$:", (lbl->key + 100));
5228         }
5229
5230       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5231       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5232
5233       aopOp (result, ic, TRUE, FALSE);
5234
5235       /* c = 1 if egal */
5236       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5237         {
5238           outBitC (result);
5239           goto release;
5240         }
5241       if (ifx)
5242         {
5243           genIfxJump (ifx, "c");
5244           goto release;
5245         }
5246       /* if the result is used in an arithmetic operation
5247          then put the result in place */
5248       outBitC (result);
5249     }
5250   else
5251     {
5252       gencjne (left, right, newiTempLabel (NULL));
5253
5254       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5255       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5256
5257       aopOp (result, ic, TRUE, FALSE);
5258
5259       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5260         {
5261           aopPut (AOP (result), "a", 0);
5262           goto release;
5263         }
5264       if (ifx)
5265         {
5266           genIfxJump (ifx, "a");
5267           goto release;
5268         }
5269       /* if the result is used in an arithmetic operation
5270          then put the result in place */
5271       if (AOP_TYPE (result) != AOP_CRY)
5272         outAcc (result);
5273       /* leave the result in acc */
5274     }
5275
5276 release:
5277   freeAsmop (result, NULL, ic, TRUE);
5278 }
5279
5280 /*-----------------------------------------------------------------*/
5281 /* ifxForOp - returns the icode containing the ifx for operand     */
5282 /*-----------------------------------------------------------------*/
5283 static iCode *
5284 ifxForOp (operand * op, iCode * ic)
5285 {
5286   /* if true symbol then needs to be assigned */
5287   if (IS_TRUE_SYMOP (op))
5288     return NULL;
5289
5290   /* if this has register type condition and
5291      the next instruction is ifx with the same operand
5292      and live to of the operand is upto the ifx only then */
5293   if (ic->next &&
5294       ic->next->op == IFX &&
5295       IC_COND (ic->next)->key == op->key &&
5296       OP_SYMBOL (op)->liveTo <= ic->next->seq)
5297     return ic->next;
5298
5299   return NULL;
5300 }
5301 /*-----------------------------------------------------------------*/
5302 /* genAndOp - for && operation                                     */
5303 /*-----------------------------------------------------------------*/
5304 static void
5305 genAndOp (iCode * ic)
5306 {
5307   operand *left, *right, *result;
5308   symbol *tlbl;
5309
5310   D (emitcode (";", "genAndOp "););
5311
5312   /* note here that && operations that are in an
5313      if statement are taken away by backPatchLabels
5314      only those used in arthmetic operations remain */
5315   AOP_OP_2 (ic);
5316   AOP_SET_LOCALS (ic);
5317
5318   /* if both are bit variables */
5319   if (AOP_TYPE (left) == AOP_CRY &&
5320       AOP_TYPE (right) == AOP_CRY)
5321     {
5322       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5323       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5324       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5325       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5326   
5327       aopOp (result,ic,FALSE, FALSE);
5328       outBitC (result);
5329     }
5330   else
5331     {
5332       tlbl = newiTempLabel (NULL);
5333       toBoolean (left);
5334       emitcode ("jz", "%05d$", tlbl->key + 100);
5335       toBoolean (right);
5336       emitcode ("", "%05d$:", tlbl->key + 100);
5337       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5338       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5339   
5340       aopOp (result,ic,FALSE, FALSE);
5341       outBitAcc (result);
5342     }
5343     freeAsmop (result, NULL, ic, TRUE);
5344 }
5345
5346
5347 /*-----------------------------------------------------------------*/
5348 /* genOrOp - for || operation                                      */
5349 /*-----------------------------------------------------------------*/
5350 static void
5351 genOrOp (iCode * ic)
5352 {
5353   operand *left, *right, *result;
5354   symbol *tlbl;
5355
5356   D (emitcode (";", "genOrOp "););
5357
5358   /* note here that || operations that are in an
5359      if statement are taken away by backPatchLabels
5360      only those used in arthmetic operations remain */
5361   AOP_OP_2 (ic);
5362   AOP_SET_LOCALS (ic);
5363
5364   /* if both are bit variables */
5365   if (AOP_TYPE (left) == AOP_CRY &&
5366       AOP_TYPE (right) == AOP_CRY)
5367     {
5368       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5369       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5370       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5371       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5372   
5373       aopOp (result,ic,FALSE, FALSE);
5374       
5375       outBitC (result);
5376     }
5377   else
5378     {
5379       tlbl = newiTempLabel (NULL);
5380       toBoolean (left);
5381       emitcode ("jnz", "%05d$", tlbl->key + 100);
5382       toBoolean (right);
5383       emitcode ("", "%05d$:", tlbl->key + 100);
5384       freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5385       freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5386   
5387       aopOp (result,ic,FALSE, FALSE);
5388       
5389       outBitAcc (result);
5390     }
5391
5392   freeAsmop (result, NULL, ic, TRUE);
5393 }
5394
5395 /*-----------------------------------------------------------------*/
5396 /* isLiteralBit - test if lit == 2^n                               */
5397 /*-----------------------------------------------------------------*/
5398 static int
5399 isLiteralBit (unsigned long lit)
5400 {
5401   unsigned long pw[32] =
5402   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5403    0x100L, 0x200L, 0x400L, 0x800L,
5404    0x1000L, 0x2000L, 0x4000L, 0x8000L,
5405    0x10000L, 0x20000L, 0x40000L, 0x80000L,
5406    0x100000L, 0x200000L, 0x400000L, 0x800000L,
5407    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5408    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5409   int idx;
5410
5411   for (idx = 0; idx < 32; idx++)
5412     if (lit == pw[idx])
5413       return idx + 1;
5414   return 0;
5415 }
5416
5417 /*-----------------------------------------------------------------*/
5418 /* continueIfTrue -                                                */
5419 /*-----------------------------------------------------------------*/
5420 static void
5421 continueIfTrue (iCode * ic)
5422 {
5423   if (IC_TRUE (ic))
5424     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5425   ic->generated = 1;
5426 }
5427
5428 /*-----------------------------------------------------------------*/
5429 /* jmpIfTrue -                                                     */
5430 /*-----------------------------------------------------------------*/
5431 static void
5432 jumpIfTrue (iCode * ic)
5433 {
5434   if (!IC_TRUE (ic))
5435     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5436   ic->generated = 1;
5437 }
5438
5439 /*-----------------------------------------------------------------*/
5440 /* jmpTrueOrFalse -                                                */
5441 /*-----------------------------------------------------------------*/
5442 static void
5443 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
5444 {
5445   // ugly but optimized by peephole
5446   if (IC_TRUE (ic))
5447     {
5448       symbol *nlbl = newiTempLabel (NULL);
5449       emitcode ("sjmp", "%05d$", nlbl->key + 100);
5450       emitcode ("", "%05d$:", tlbl->key + 100);
5451       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5452       emitcode ("", "%05d$:", nlbl->key + 100);
5453     }
5454   else
5455     {
5456       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5457       emitcode ("", "%05d$:", tlbl->key + 100);
5458     }
5459   ic->generated = 1;
5460 }
5461
5462 // Generate code to perform a bit-wise logic operation
5463 // on two operands in far space (assumed to already have been 
5464 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
5465 // in far space. This requires pushing the result on the stack
5466 // then popping it into the result.
5467 static void
5468 genFarFarLogicOp(iCode *ic, char *logicOp)
5469 {
5470       int size, resultSize, compSize;
5471       int offset = 0;
5472       
5473       TR_AP("#5");
5474       D(emitcode(";", "%s special case for 3 far operands.", logicOp););
5475       compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? 
5476                   AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
5477       
5478       _startLazyDPSEvaluation();
5479       for (size = compSize; (size--); offset++)
5480       {
5481           MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE));
5482           emitcode ("mov", "%s, acc", DP2_RESULT_REG);
5483           MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE));
5484           
5485           emitcode (logicOp, "a,%s", DP2_RESULT_REG);
5486           emitcode ("push", "acc");
5487       }
5488       _endLazyDPSEvaluation();
5489      
5490       freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5491       freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
5492       aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
5493      
5494       resultSize = AOP_SIZE(IC_RESULT(ic));
5495
5496       ADJUST_PUSHED_RESULT(compSize, resultSize);
5497
5498       _startLazyDPSEvaluation();
5499       while (compSize--)
5500       {
5501           emitcode ("pop", "acc");
5502           aopPut (AOP (IC_RESULT (ic)), "a", compSize);
5503       }
5504       _endLazyDPSEvaluation();
5505       freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
5506 }
5507
5508
5509 /*-----------------------------------------------------------------*/
5510 /* genAnd  - code for and                                          */
5511 /*-----------------------------------------------------------------*/
5512 static void
5513 genAnd (iCode * ic, iCode * ifx)
5514 {
5515   operand *left, *right, *result;
5516   int size, offset = 0;
5517   unsigned long lit = 0L;
5518   int bytelit = 0;
5519   char buffer[10];
5520   bool pushResult;
5521
5522   D (emitcode (";", "genAnd "););
5523
5524   AOP_OP_3_NOFATAL (ic, pushResult);
5525   AOP_SET_LOCALS (ic);
5526
5527   if (pushResult)
5528   {
5529       genFarFarLogicOp(ic, "anl");
5530       return;
5531   }  
5532
5533 #ifdef DEBUG_TYPE
5534   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5535             AOP_TYPE (result),
5536             AOP_TYPE (left), AOP_TYPE (right));
5537   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5538             AOP_SIZE (result),
5539             AOP_SIZE (left), AOP_SIZE (right));
5540 #endif
5541
5542   /* if left is a literal & right is not then exchange them */
5543   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5544 #ifdef LOGIC_OPS_BROKEN      
5545     ||  AOP_NEEDSACC (left)
5546 #endif
5547     )
5548     {
5549       operand *tmp = right;
5550       right = left;
5551       left = tmp;
5552     }
5553
5554   /* if result = right then exchange them */
5555   if (sameRegs (AOP (result), AOP (right)))
5556     {
5557       operand *tmp = right;
5558       right = left;
5559       left = tmp;
5560     }
5561
5562   /* if right is bit then exchange them */
5563   if (AOP_TYPE (right) == AOP_CRY &&
5564       AOP_TYPE (left) != AOP_CRY)
5565     {
5566       operand *tmp = right;
5567       right = left;
5568       left = tmp;
5569     }
5570   if (AOP_TYPE (right) == AOP_LIT)
5571     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5572
5573   size = AOP_SIZE (result);
5574
5575   // if(bit & yy)
5576   // result = bit & yy;
5577   if (AOP_TYPE (left) == AOP_CRY)
5578     {
5579       // c = bit & literal;
5580       if (AOP_TYPE (right) == AOP_LIT)
5581         {
5582           if (lit & 1)
5583             {
5584               if (size && sameRegs (AOP (result), AOP (left)))
5585                 // no change
5586                 goto release;
5587               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5588             }
5589           else
5590             {
5591               // bit(result) = 0;
5592               if (size && (AOP_TYPE (result) == AOP_CRY))
5593                 {
5594                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5595                   goto release;
5596                 }
5597               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5598                 {
5599                   jumpIfTrue (ifx);
5600                   goto release;
5601                 }
5602               emitcode ("clr", "c");
5603             }
5604         }
5605       else
5606         {
5607           if (AOP_TYPE (right) == AOP_CRY)
5608             {
5609               // c = bit & bit;
5610               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5611               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5612             }
5613           else
5614             {
5615               // c = bit & val;
5616               MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
5617               // c = lsb
5618               emitcode ("rrc", "a");
5619               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5620             }
5621         }
5622       // bit = c
5623       // val = c
5624       if (size)
5625         outBitC (result);
5626       // if(bit & ...)
5627       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5628         genIfxJump (ifx, "c");
5629       goto release;
5630     }
5631
5632   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5633   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5634   if ((AOP_TYPE (right) == AOP_LIT) &&
5635       (AOP_TYPE (result) == AOP_CRY) &&
5636       (AOP_TYPE (left) != AOP_CRY))
5637     {
5638       int posbit = isLiteralBit (lit);
5639       /* left &  2^n */
5640       if (posbit)
5641         {
5642           posbit--;
5643           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE));
5644           // bit = left & 2^n
5645           if (size)
5646             emitcode ("mov", "c,acc.%d", posbit & 0x07);
5647           // if(left &  2^n)
5648           else
5649             {
5650               if (ifx)
5651                 {
5652                   sprintf (buffer, "acc.%d", posbit & 0x07);
5653                   genIfxJump (ifx, buffer);
5654                 }
5655               goto release;
5656             }
5657         }
5658       else
5659         {
5660           symbol *tlbl = newiTempLabel (NULL);
5661           int sizel = AOP_SIZE (left);
5662           if (size)
5663             emitcode ("setb", "c");
5664           while (sizel--)
5665             {
5666               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5667                 {
5668                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5669                   // byte ==  2^n ?
5670                   if ((posbit = isLiteralBit (bytelit)) != 0)
5671                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5672                   else
5673                     {
5674                       if (bytelit != 0x0FFL)
5675                         emitcode ("anl", "a,%s",
5676                           aopGet (AOP (right), offset, FALSE, TRUE, FALSE));
5677                       emitcode ("jnz", "%05d$", tlbl->key + 100);
5678                     }
5679                 }
5680               offset++;
5681             }
5682           // bit = left & literal
5683           if (size)
5684             {
5685               emitcode ("clr", "c");
5686               emitcode ("", "%05d$:", tlbl->key + 100);
5687             }
5688           // if(left & literal)
5689           else
5690             {
5691               if (ifx)
5692                 jmpTrueOrFalse (ifx, tlbl);
5693               goto release;
5694             }
5695         }
5696       outBitC (result);
5697       goto release;
5698     }
5699
5700   /* if left is same as result */
5701   if (sameRegs (AOP (result), AOP (left)))
5702     {
5703       for (; size--; offset++)
5704         {
5705           if (AOP_TYPE (right) == AOP_LIT)
5706             {
5707               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5708                 continue;
5709               else if (bytelit == 0)
5710                 aopPut (AOP (result), zero, offset);
5711               else if (IS_AOP_PREG (result))
5712                 {
5713                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5714                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5715                   aopPut (AOP (result), "a", offset);
5716                 }
5717               else
5718                 emitcode ("anl", "%s,%s",
5719                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
5720                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5721             }
5722           else
5723             {
5724               if (AOP_TYPE (left) == AOP_ACC)
5725                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5726               else
5727                 {
5728                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5729                   if (IS_AOP_PREG (result))
5730                     {
5731                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5732                       aopPut (AOP (result), "a", offset);
5733
5734                     }
5735                   else
5736                     emitcode ("anl", "%s,a",
5737                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
5738                 }
5739             }
5740         }
5741     }
5742   else
5743     {
5744       // left & result in different registers
5745       if (AOP_TYPE (result) == AOP_CRY)
5746         {
5747           // result = bit
5748           // if(size), result in bit
5749           // if(!size && ifx), conditional oper: if(left & right)
5750           symbol *tlbl = newiTempLabel (NULL);
5751           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5752           if (size)
5753             emitcode ("setb", "c");
5754           while (sizer--)
5755             {
5756               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5757                 emitcode ("anl", "a,%s",
5758                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
5759               } else {
5760                 if (AOP_TYPE(left)==AOP_ACC) {
5761                   emitcode("mov", "b,a");
5762                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5763                   emitcode("anl", "a,b");
5764                 }else {
5765                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
5766                   emitcode ("anl", "a,%s",
5767                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
5768                 }
5769               }
5770               emitcode ("jnz", "%05d$", tlbl->key + 100);
5771               offset++;
5772             }
5773           if (size)
5774             {
5775               CLRC;
5776               emitcode ("", "%05d$:", tlbl->key + 100);
5777               outBitC (result);
5778             }
5779           else if (ifx)
5780             jmpTrueOrFalse (ifx, tlbl);
5781         }
5782       else
5783         {
5784           for (; (size--); offset++)
5785             {
5786               // normal case
5787               // result = left & right
5788               if (AOP_TYPE (right) == AOP_LIT)
5789                 {
5790                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5791                     {
5792                       aopPut (AOP (result),
5793                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
5794                               offset);
5795                       continue;
5796                     }
5797                   else if (bytelit == 0)
5798                     {
5799                       aopPut (AOP (result), zero, offset);
5800                       continue;
5801                     }
5802                   D (emitcode (";", "better literal AND."););
5803                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5804                   emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
5805                                                     FALSE, FALSE, FALSE));
5806
5807                 }
5808               else
5809                 {
5810                   // faster than result <- left, anl result,right
5811                   // and better if result is SFR
5812                   if (AOP_TYPE (left) == AOP_ACC)
5813                     {
5814                       emitcode ("anl", "a,%s", aopGet (AOP (right), offset,
5815                                                        FALSE, FALSE, FALSE));
5816                     }
5817                   else
5818                     {
5819                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
5820                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
5821                       {
5822                           emitcode("mov", "b,a");
5823                           rOp = "b";
5824                       }
5825                         
5826                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
5827                       emitcode ("anl", "a,%s", rOp);
5828                     }                   
5829                 }
5830               aopPut (AOP (result), "a", offset);
5831             }
5832         }
5833     }
5834
5835 release:
5836   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5837   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5838   freeAsmop (result, NULL, ic, TRUE);
5839 }
5840
5841
5842 /*-----------------------------------------------------------------*/
5843 /* genOr  - code for or                                            */
5844 /*-----------------------------------------------------------------*/
5845 static void
5846 genOr (iCode * ic, iCode * ifx)
5847 {
5848   operand *left, *right, *result;
5849   int size, offset = 0;
5850   unsigned long lit = 0L;
5851   bool     pushResult;
5852
5853   D (emitcode (";", "genOr "););
5854
5855   AOP_OP_3_NOFATAL (ic, pushResult);
5856   AOP_SET_LOCALS (ic);
5857
5858   if (pushResult)
5859   {
5860       genFarFarLogicOp(ic, "orl");
5861       return;
5862   }
5863
5864
5865 #ifdef DEBUG_TYPE
5866   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5867             AOP_TYPE (result),
5868             AOP_TYPE (left), AOP_TYPE (right));
5869   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5870             AOP_SIZE (result),
5871             AOP_SIZE (left), AOP_SIZE (right));
5872 #endif
5873
5874   /* if left is a literal & right is not then exchange them */
5875   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5876 #ifdef LOGIC_OPS_BROKEN
5877    || AOP_NEEDSACC (left) // I think this is a net loss now.
5878 #endif      
5879       )
5880     {
5881       operand *tmp = right;
5882       right = left;
5883       left = tmp;
5884     }
5885
5886   /* if result = right then exchange them */
5887   if (sameRegs (AOP (result), AOP (right)))
5888     {
5889       operand *tmp = right;
5890       right = left;
5891       left = tmp;
5892     }
5893
5894   /* if right is bit then exchange them */
5895   if (AOP_TYPE (right) == AOP_CRY &&
5896       AOP_TYPE (left) != AOP_CRY)
5897     {
5898       operand *tmp = right;
5899       right = left;
5900       left = tmp;
5901     }
5902   if (AOP_TYPE (right) == AOP_LIT)
5903     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5904
5905   size = AOP_SIZE (result);
5906
5907   // if(bit | yy)
5908   // xx = bit | yy;
5909   if (AOP_TYPE (left) == AOP_CRY)
5910     {
5911       if (AOP_TYPE (right) == AOP_LIT)
5912         {
5913           // c = bit & literal;
5914           if (lit)
5915             {
5916               // lit != 0 => result = 1
5917               if (AOP_TYPE (result) == AOP_CRY)
5918                 {
5919                   if (size)
5920                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5921                   else if (ifx)
5922                     continueIfTrue (ifx);
5923                   goto release;
5924                 }
5925               emitcode ("setb", "c");
5926             }
5927           else
5928             {
5929               // lit == 0 => result = left
5930               if (size && sameRegs (AOP (result), AOP (left)))
5931                 goto release;
5932               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5933             }
5934         }
5935       else
5936         {
5937           if (AOP_TYPE (right) == AOP_CRY)
5938             {
5939               // c = bit | bit;
5940               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5941               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5942             }
5943           else
5944             {
5945               // c = bit | val;
5946               symbol *tlbl = newiTempLabel (NULL);
5947               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5948                 emitcode ("setb", "c");
5949               emitcode ("jb", "%s,%05d$",
5950                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
5951               toBoolean (right);
5952               emitcode ("jnz", "%05d$", tlbl->key + 100);
5953               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5954                 {
5955                   jmpTrueOrFalse (ifx, tlbl);
5956                   goto release;
5957                 }
5958               else
5959                 {
5960                   CLRC;
5961                   emitcode ("", "%05d$:", tlbl->key + 100);
5962                 }
5963             }
5964         }
5965       // bit = c
5966       // val = c
5967       if (size)
5968         outBitC (result);
5969       // if(bit | ...)
5970       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5971         genIfxJump (ifx, "c");
5972       goto release;
5973     }
5974
5975   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5976   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5977   if ((AOP_TYPE (right) == AOP_LIT) &&
5978       (AOP_TYPE (result) == AOP_CRY) &&
5979       (AOP_TYPE (left) != AOP_CRY))
5980     {
5981       if (lit)
5982         {
5983           // result = 1
5984           if (size)
5985             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5986           else
5987             continueIfTrue (ifx);
5988           goto release;
5989         }
5990       else
5991         {
5992           // lit = 0, result = boolean(left)
5993           if (size)
5994             emitcode ("setb", "c");
5995           toBoolean (right);
5996           if (size)
5997             {
5998               symbol *tlbl = newiTempLabel (NULL);
5999               emitcode ("jnz", "%05d$", tlbl->key + 100);
6000               CLRC;
6001               emitcode ("", "%05d$:", tlbl->key + 100);
6002             }
6003           else
6004             {
6005               genIfxJump (ifx, "a");
6006               goto release;
6007             }
6008         }
6009       outBitC (result);
6010       goto release;
6011     }
6012
6013   /* if left is same as result */
6014   if (sameRegs (AOP (result), AOP (left)))
6015     {
6016       for (; size--; offset++)
6017         {
6018           if (AOP_TYPE (right) == AOP_LIT)
6019             {
6020               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6021                 {
6022                   continue;
6023                 }
6024               else
6025                 {
6026                   if (IS_AOP_PREG (left))
6027                     {
6028                       MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6029                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6030                       aopPut (AOP (result), "a", offset);
6031                     }
6032                   else
6033                     {
6034                       emitcode ("orl", "%s,%s",
6035                             aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6036                          aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6037                     }
6038                 }
6039             }
6040           else
6041             {
6042               if (AOP_TYPE (left) == AOP_ACC)
6043                 {
6044                   emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6045                 }
6046               else
6047                 {
6048                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6049                   if (IS_AOP_PREG (left))
6050                     {
6051                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6052                       aopPut (AOP (result), "a", offset);
6053                     }
6054                   else
6055                     {
6056                       emitcode ("orl", "%s,a",
6057                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6058                     }
6059                 }
6060             }
6061         }
6062     }
6063   else
6064     {
6065       // left & result in different registers
6066       if (AOP_TYPE (result) == AOP_CRY)
6067         {
6068           // result = bit
6069           // if(size), result in bit
6070           // if(!size && ifx), conditional oper: if(left | right)
6071           symbol *tlbl = newiTempLabel (NULL);
6072           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6073           if (size)
6074             emitcode ("setb", "c");
6075           while (sizer--)
6076             {
6077               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6078                 emitcode ("orl", "a,%s",
6079                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6080               } else {
6081                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6082                 emitcode ("orl", "a,%s",
6083                           aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6084               }
6085               emitcode ("jnz", "%05d$", tlbl->key + 100);
6086               offset++;
6087             }
6088           if (size)
6089             {
6090               CLRC;
6091               emitcode ("", "%05d$:", tlbl->key + 100);
6092               outBitC (result);
6093             }
6094           else if (ifx)
6095             jmpTrueOrFalse (ifx, tlbl);
6096         }
6097       else
6098         {
6099             _startLazyDPSEvaluation();
6100           for (; (size--); offset++)
6101             {
6102               // normal case
6103               // result = left & right
6104               if (AOP_TYPE (right) == AOP_LIT)
6105                 {
6106                   if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6107                     {
6108                       aopPut (AOP (result),
6109                            aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6110                               offset);
6111                       continue;
6112                     }
6113                   D (emitcode (";", "better literal OR."););
6114                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6115                   emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
6116                                                     FALSE, FALSE, FALSE));
6117
6118                 }
6119               else
6120                 {
6121                   // faster than result <- left, anl result,right
6122                   // and better if result is SFR
6123                   if (AOP_TYPE (left) == AOP_ACC)
6124                     {
6125                       emitcode ("orl", "a,%s", aopGet (AOP (right), offset,
6126                                                        FALSE, FALSE, FALSE));
6127                     }
6128                   else
6129                     {
6130                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6131                         
6132                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6133                       {
6134                           emitcode("mov", "b,a");
6135                           rOp = "b";
6136                       }
6137                         
6138                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6139                       emitcode ("orl", "a,%s", rOp);
6140                     }
6141                 }
6142               aopPut (AOP (result), "a", offset);
6143             }
6144             _endLazyDPSEvaluation();
6145         }
6146     }
6147
6148 release:
6149   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6150   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6151   freeAsmop (result, NULL, ic, TRUE);
6152 }
6153
6154 /*-----------------------------------------------------------------*/
6155 /* genXor - code for xclusive or                                   */
6156 /*-----------------------------------------------------------------*/
6157 static void
6158 genXor (iCode * ic, iCode * ifx)
6159 {
6160   operand *left, *right, *result;
6161   int size, offset = 0;
6162   unsigned long lit = 0L;
6163   bool pushResult;
6164
6165   D (emitcode (";", "genXor "););
6166
6167   AOP_OP_3_NOFATAL (ic, pushResult);
6168   AOP_SET_LOCALS (ic);
6169
6170   if (pushResult)
6171   {
6172       genFarFarLogicOp(ic, "xrl");
6173       return;
6174   }  
6175
6176 #ifdef DEBUG_TYPE
6177   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6178             AOP_TYPE (result),
6179             AOP_TYPE (left), AOP_TYPE (right));
6180   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6181             AOP_SIZE (result),
6182             AOP_SIZE (left), AOP_SIZE (right));
6183 #endif
6184
6185   /* if left is a literal & right is not ||
6186      if left needs acc & right does not */
6187   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
6188 #ifdef LOGIC_OPS_BROKEN      
6189       || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6190 #endif
6191      )
6192     {
6193       operand *tmp = right;
6194       right = left;
6195       left = tmp;
6196     }
6197
6198   /* if result = right then exchange them */
6199   if (sameRegs (AOP (result), AOP (right)))
6200     {
6201       operand *tmp = right;
6202       right = left;
6203       left = tmp;
6204     }
6205
6206   /* if right is bit then exchange them */
6207   if (AOP_TYPE (right) == AOP_CRY &&
6208       AOP_TYPE (left) != AOP_CRY)
6209     {
6210       operand *tmp = right;
6211       right = left;
6212       left = tmp;
6213     }
6214   if (AOP_TYPE (right) == AOP_LIT)
6215     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6216
6217   size = AOP_SIZE (result);
6218
6219   // if(bit ^ yy)
6220   // xx = bit ^ yy;
6221   if (AOP_TYPE (left) == AOP_CRY)
6222     {
6223       if (AOP_TYPE (right) == AOP_LIT)
6224         {
6225           // c = bit & literal;
6226           if (lit >> 1)
6227             {
6228               // lit>>1  != 0 => result = 1
6229               if (AOP_TYPE (result) == AOP_CRY)
6230                 {
6231                   if (size)
6232                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6233                   else if (ifx)
6234                     continueIfTrue (ifx);
6235                   goto release;
6236                 }
6237               emitcode ("setb", "c");
6238             }
6239           else
6240             {
6241               // lit == (0 or 1)
6242               if (lit == 0)
6243                 {
6244                   // lit == 0, result = left
6245                   if (size && sameRegs (AOP (result), AOP (left)))
6246                     goto release;
6247                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6248                 }
6249               else
6250                 {
6251                   // lit == 1, result = not(left)
6252                   if (size && sameRegs (AOP (result), AOP (left)))
6253                     {
6254                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6255                       goto release;
6256                     }
6257                   else
6258                     {
6259                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6260                       emitcode ("cpl", "c");
6261                     }
6262                 }
6263             }
6264
6265         }
6266       else
6267         {
6268           // right != literal
6269           symbol *tlbl = newiTempLabel (NULL);
6270           if (AOP_TYPE (right) == AOP_CRY)
6271             {
6272               // c = bit ^ bit;
6273               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6274             }
6275           else
6276             {
6277               int sizer = AOP_SIZE (right);
6278               // c = bit ^ val
6279               // if val>>1 != 0, result = 1
6280               emitcode ("setb", "c");
6281               while (sizer)
6282                 {
6283                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE));
6284                   if (sizer == 1)
6285                     // test the msb of the lsb
6286                     emitcode ("anl", "a,#0xfe");
6287                   emitcode ("jnz", "%05d$", tlbl->key + 100);
6288                   sizer--;
6289                 }
6290               // val = (0,1)
6291               emitcode ("rrc", "a");
6292             }
6293           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6294           emitcode ("cpl", "c");
6295           emitcode ("", "%05d$:", (tlbl->key + 100));
6296         }
6297       // bit = c
6298       // val = c
6299       if (size)
6300         outBitC (result);
6301       // if(bit | ...)
6302       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6303         genIfxJump (ifx, "c");
6304       goto release;
6305     }
6306
6307   if (sameRegs (AOP (result), AOP (left)))
6308     {
6309       /* if left is same as result */
6310       for (; size--; offset++)
6311         {
6312           if (AOP_TYPE (right) == AOP_LIT)
6313             {
6314               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6315                 continue;
6316               else if (IS_AOP_PREG (left))
6317                 {
6318                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6319                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6320                   aopPut (AOP (result), "a", offset);
6321                 }
6322               else
6323                 emitcode ("xrl", "%s,%s",
6324                           aopGet (AOP (left), offset, FALSE, TRUE, FALSE),
6325                           aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6326             }
6327           else
6328             {
6329               if (AOP_TYPE (left) == AOP_ACC)
6330                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6331               else
6332                 {
6333                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6334                   if (IS_AOP_PREG (left))
6335                     {
6336                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6337                       aopPut (AOP (result), "a", offset);
6338                     }
6339                   else
6340                     emitcode ("xrl", "%s,a",
6341                            aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
6342                 }
6343             }
6344         }
6345     }
6346   else
6347     {
6348       // left & result in different registers
6349       if (AOP_TYPE (result) == AOP_CRY)
6350         {
6351           // result = bit
6352           // if(size), result in bit
6353           // if(!size && ifx), conditional oper: if(left ^ right)
6354           symbol *tlbl = newiTempLabel (NULL);
6355           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6356           if (size)
6357             emitcode ("setb", "c");
6358           while (sizer--)
6359             {
6360               if ((AOP_TYPE (right) == AOP_LIT) &&
6361                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6362                 {
6363                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6364                 }
6365               else
6366                 {
6367                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6368                     emitcode ("xrl", "a,%s",
6369                               aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
6370                   } else {
6371                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
6372                     emitcode ("xrl", "a,%s",
6373                               aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
6374                   }
6375                 }
6376               emitcode ("jnz", "%05d$", tlbl->key + 100);
6377               offset++;
6378             }
6379           if (size)
6380             {
6381               CLRC;
6382               emitcode ("", "%05d$:", tlbl->key + 100);
6383               outBitC (result);
6384             }
6385           else if (ifx)
6386             jmpTrueOrFalse (ifx, tlbl);
6387         }
6388       else
6389         for (; (size--); offset++)
6390           {
6391             // normal case
6392             // result = left & right
6393             if (AOP_TYPE (right) == AOP_LIT)
6394               {
6395                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6396                   {
6397                     aopPut (AOP (result),
6398                             aopGet (AOP (left), offset, FALSE, FALSE, FALSE),
6399                             offset);
6400                     continue;
6401                   }
6402                 D (emitcode (";", "better literal XOR.");
6403                   );
6404                 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6405                 emitcode ("xrl", "a, %s", aopGet (AOP (right), offset,
6406                                                   FALSE, FALSE, FALSE));
6407               }
6408             else
6409               {
6410                 // faster than result <- left, anl result,right
6411                 // and better if result is SFR
6412                 if (AOP_TYPE (left) == AOP_ACC)
6413                   {
6414                     emitcode ("xrl", "a,%s", aopGet (AOP (right), offset,
6415                                                      FALSE, FALSE, FALSE));
6416                   }
6417                 else
6418                   {
6419                       char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
6420                       if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6421                       {
6422                           emitcode("mov", "b,a");
6423                           rOp = "b";
6424                       }
6425                         
6426                       MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
6427                       emitcode ("xrl", "a,%s", rOp);
6428                   }
6429               }
6430             aopPut (AOP (result), "a", offset);
6431           }
6432     }
6433
6434 release:
6435   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6436   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6437   freeAsmop (result, NULL, ic, TRUE);
6438 }
6439
6440 /*-----------------------------------------------------------------*/
6441 /* genInline - write the inline code out                           */
6442 /*-----------------------------------------------------------------*/
6443 static void
6444 genInline (iCode * ic)
6445 {
6446   char *buffer, *bp, *bp1;
6447
6448   D (emitcode (";", "genInline ");
6449     );
6450
6451   _G.inLine += (!options.asmpeep);
6452
6453   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6454   strcpy (buffer, IC_INLINE (ic));
6455
6456   /* emit each line as a code */
6457   while (*bp)
6458     {
6459       if (*bp == '\n')
6460         {
6461           *bp++ = '\0';
6462           emitcode (bp1, "");
6463           bp1 = bp;
6464         }
6465       else
6466         {
6467           if (*bp == ':')
6468             {
6469               bp++;
6470               *bp = '\0';
6471               bp++;
6472               emitcode (bp1, "");
6473               bp1 = bp;
6474             }
6475           else
6476             bp++;
6477         }
6478     }
6479   if (bp1 != bp)
6480     emitcode (bp1, "");
6481   /*     emitcode("",buffer); */
6482   _G.inLine -= (!options.asmpeep);
6483 }
6484
6485 /*-----------------------------------------------------------------*/
6486 /* genRRC - rotate right with carry                                */
6487 /*-----------------------------------------------------------------*/
6488 static void
6489 genRRC (iCode * ic)
6490 {
6491   operand *left, *result;
6492   int size, offset = 0;
6493   char *l;
6494
6495   D (emitcode (";", "genRRC ");
6496     );
6497
6498   /* rotate right with carry */
6499   left = IC_LEFT (ic);
6500   result = IC_RESULT (ic);
6501   aopOp (left, ic, FALSE, FALSE);
6502   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6503
6504   /* move it to the result */
6505   size = AOP_SIZE (result);
6506   offset = size - 1;
6507   CLRC;
6508
6509   _startLazyDPSEvaluation ();
6510   while (size--)
6511     {
6512       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6513       MOVA (l);
6514       emitcode ("rrc", "a");
6515       if (AOP_SIZE (result) > 1)
6516         aopPut (AOP (result), "a", offset--);
6517     }
6518   _endLazyDPSEvaluation ();
6519
6520   /* now we need to put the carry into the
6521      highest order byte of the result */
6522   if (AOP_SIZE (result) > 1)
6523     {
6524       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE);
6525       MOVA (l);
6526     }
6527   emitcode ("mov", "acc.7,c");
6528   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
6529   freeAsmop (left, NULL, ic, TRUE);
6530   freeAsmop (result, NULL, ic, TRUE);
6531 }
6532
6533 /*-----------------------------------------------------------------*/
6534 /* genRLC - generate code for rotate left with carry               */
6535 /*-----------------------------------------------------------------*/
6536 static void
6537 genRLC (iCode * ic)
6538 {
6539   operand *left, *result;
6540   int size, offset = 0;
6541   char *l;
6542
6543   D (emitcode (";", "genRLC ");
6544     );
6545
6546   /* rotate right with carry */
6547   left = IC_LEFT (ic);
6548   result = IC_RESULT (ic);
6549   aopOp (left, ic, FALSE, FALSE);
6550   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6551
6552   /* move it to the result */
6553   size = AOP_SIZE (result);
6554   offset = 0;
6555   if (size--)
6556     {
6557       l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6558       MOVA (l);
6559       emitcode ("add", "a,acc");
6560       if (AOP_SIZE (result) > 1)
6561         {
6562           aopPut (AOP (result), "a", offset++);
6563         }
6564
6565       _startLazyDPSEvaluation ();
6566       while (size--)
6567         {
6568           l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE);
6569           MOVA (l);
6570           emitcode ("rlc", "a");
6571           if (AOP_SIZE (result) > 1)
6572             aopPut (AOP (result), "a", offset++);
6573         }
6574       _endLazyDPSEvaluation ();
6575     }
6576   /* now we need to put the carry into the
6577      highest order byte of the result */
6578   if (AOP_SIZE (result) > 1)
6579     {
6580       l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE);
6581       MOVA (l);
6582     }
6583   emitcode ("mov", "acc.0,c");
6584   aopPut (AOP (result), "a", 0);
6585   freeAsmop (left, NULL, ic, TRUE);
6586   freeAsmop (result, NULL, ic, TRUE);
6587 }
6588
6589 /*-----------------------------------------------------------------*/
6590 /* genGetHbit - generates code get highest order bit               */
6591 /*-----------------------------------------------------------------*/
6592 static void
6593 genGetHbit (iCode * ic)
6594 {
6595   operand *left, *result;
6596   left = IC_LEFT (ic);
6597   result = IC_RESULT (ic);
6598   aopOp (left, ic, FALSE, FALSE);
6599   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
6600
6601   D (emitcode (";", "genGetHbit ");
6602     );
6603
6604   /* get the highest order byte into a */
6605   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE));
6606   if (AOP_TYPE (result) == AOP_CRY)
6607     {
6608       emitcode ("rlc", "a");
6609       outBitC (result);
6610     }
6611   else
6612     {
6613       emitcode ("rl", "a");
6614       emitcode ("anl", "a,#0x01");
6615       outAcc (result);
6616     }
6617
6618
6619   freeAsmop (left, NULL, ic, TRUE);
6620   freeAsmop (result, NULL, ic, TRUE);
6621 }
6622
6623 /*-----------------------------------------------------------------*/
6624 /* AccRol - rotate left accumulator by known count                 */
6625 /*-----------------------------------------------------------------*/
6626 static void
6627 AccRol (int shCount)
6628 {
6629   shCount &= 0x0007;            // shCount : 0..7
6630
6631   switch (shCount)
6632     {
6633     case 0:
6634       break;
6635     case 1:
6636       emitcode ("rl", "a");
6637       break;
6638     case 2:
6639       emitcode ("rl", "a");
6640       emitcode ("rl", "a");
6641       break;
6642     case 3:
6643       emitcode ("swap", "a");
6644       emitcode ("rr", "a");
6645       break;
6646     case 4:
6647       emitcode ("swap", "a");
6648       break;
6649     case 5:
6650       emitcode ("swap", "a");
6651       emitcode ("rl", "a");
6652       break;
6653     case 6:
6654       emitcode ("rr", "a");
6655       emitcode ("rr", "a");
6656       break;
6657     case 7:
6658       emitcode ("rr", "a");
6659       break;
6660     }
6661 }
6662
6663 /*-----------------------------------------------------------------*/
6664 /* AccLsh - left shift accumulator by known count                  */
6665 /*-----------------------------------------------------------------*/
6666 static void
6667 AccLsh (int shCount)
6668 {
6669   if (shCount != 0)
6670     {
6671       if (shCount == 1)
6672         emitcode ("add", "a,acc");
6673       else if (shCount == 2)
6674         {
6675           emitcode ("add", "a,acc");
6676           emitcode ("add", "a,acc");
6677         }
6678       else
6679         {
6680           /* rotate left accumulator */
6681           AccRol (shCount);
6682           /* and kill the lower order bits */
6683           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6684         }
6685     }
6686 }
6687
6688 /*-----------------------------------------------------------------*/
6689 /* AccRsh - right shift accumulator by known count                 */
6690 /*-----------------------------------------------------------------*/
6691 static void
6692 AccRsh (int shCount)
6693 {
6694   if (shCount != 0)
6695     {
6696       if (shCount == 1)
6697         {
6698           CLRC;
6699           emitcode ("rrc", "a");
6700         }
6701       else
6702         {
6703           /* rotate right accumulator */
6704           AccRol (8 - shCount);
6705           /* and kill the higher order bits */
6706           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6707         }
6708     }
6709 }
6710
6711 #ifdef BETTER_LITERAL_SHIFT
6712 /*-----------------------------------------------------------------*/
6713 /* AccSRsh - signed right shift accumulator by known count                 */
6714 /*-----------------------------------------------------------------*/
6715 static void
6716 AccSRsh (int shCount)
6717 {
6718   symbol *tlbl;
6719   if (shCount != 0)
6720     {
6721       if (shCount == 1)
6722         {
6723           emitcode ("mov", "c,acc.7");
6724           emitcode ("rrc", "a");
6725         }
6726       else if (shCount == 2)
6727         {
6728           emitcode ("mov", "c,acc.7");
6729           emitcode ("rrc", "a");
6730           emitcode ("mov", "c,acc.7");
6731           emitcode ("rrc", "a");
6732         }
6733       else
6734         {
6735           tlbl = newiTempLabel (NULL);
6736           /* rotate right accumulator */
6737           AccRol (8 - shCount);
6738           /* and kill the higher order bits */
6739           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6740           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6741           emitcode ("orl", "a,#0x%02x",
6742                     (unsigned char) ~SRMask[shCount]);
6743           emitcode ("", "%05d$:", tlbl->key + 100);
6744         }
6745     }
6746 }
6747 #endif
6748
6749 #ifdef BETTER_LITERAL_SHIFT
6750 /*-----------------------------------------------------------------*/
6751 /* shiftR1Left2Result - shift right one byte from left to result   */
6752 /*-----------------------------------------------------------------*/
6753 static void
6754 shiftR1Left2Result (operand * left, int offl,
6755                     operand * result, int offr,
6756                     int shCount, int sign)
6757 {
6758   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6759   /* shift right accumulator */
6760   if (sign)
6761     AccSRsh (shCount);
6762   else
6763     AccRsh (shCount);
6764   aopPut (AOP (result), "a", offr);
6765 }
6766 #endif
6767
6768 #ifdef BETTER_LITERAL_SHIFT
6769 /*-----------------------------------------------------------------*/
6770 /* shiftL1Left2Result - shift left one byte from left to result    */
6771 /*-----------------------------------------------------------------*/
6772 static void
6773 shiftL1Left2Result (operand * left, int offl,
6774                     operand * result, int offr, int shCount)
6775 {
6776   MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
6777   /* shift left accumulator */
6778   AccLsh (shCount);
6779   aopPut (AOP (result), "a", offr);
6780 }
6781 #endif
6782
6783 #ifdef BETTER_LITERAL_SHIFT
6784 /*-----------------------------------------------------------------*/
6785 /* movLeft2Result - move byte from left to result                  */
6786 /*-----------------------------------------------------------------*/
6787 static void
6788 movLeft2Result (operand * left, int offl,
6789                 operand * result, int offr, int sign)
6790 {
6791   char *l;
6792   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6793   {
6794       l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE);
6795
6796       if (*l == '@' && (IS_AOP_PREG (result)))
6797       {
6798           emitcode ("mov", "a,%s", l);
6799           aopPut (AOP (result), "a", offr);
6800       }
6801       else
6802       {
6803           if (!sign)
6804           {
6805             aopPut (AOP (result), l, offr);
6806           }
6807           else
6808             {
6809               /* MSB sign in acc.7 ! */
6810               if (getDataSize (left) == offl + 1)
6811                 {
6812                   emitcode ("mov", "a,%s", l);
6813                   aopPut (AOP (result), "a", offr);
6814                 }
6815             }
6816       }
6817   }
6818 }
6819 #endif
6820
6821 #ifdef BETTER_LITERAL_SHIFT
6822 /*-----------------------------------------------------------------*/
6823 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
6824 /*-----------------------------------------------------------------*/
6825 static void
6826 AccAXRrl1 (char *x)
6827 {
6828   emitcode ("rrc", "a");
6829   emitcode ("xch", "a,%s", x);
6830   emitcode ("rrc", "a");
6831   emitcode ("xch", "a,%s", x);
6832 }
6833 #endif
6834
6835 #ifdef BETTER_LITERAL_SHIFT
6836 //REMOVE ME!!!
6837 /*-----------------------------------------------------------------*/
6838 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
6839 /*-----------------------------------------------------------------*/
6840 static void
6841 AccAXLrl1 (char *x)
6842 {
6843   emitcode ("xch", "a,%s", x);
6844   emitcode ("rlc", "a");
6845   emitcode ("xch", "a,%s", x);
6846   emitcode ("rlc", "a");
6847 }
6848 #endif
6849
6850 #ifdef BETTER_LITERAL_SHIFT
6851 /*-----------------------------------------------------------------*/
6852 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
6853 /*-----------------------------------------------------------------*/
6854 static void
6855 AccAXLsh1 (char *x)
6856 {
6857   emitcode ("xch", "a,%s", x);
6858   emitcode ("add", "a,acc");
6859   emitcode ("xch", "a,%s", x);
6860   emitcode ("rlc", "a");
6861 }
6862 #endif
6863
6864 #ifdef BETTER_LITERAL_SHIFT
6865 /*-----------------------------------------------------------------*/
6866 /* AccAXLsh - left shift a:x by known count (0..7)                 */
6867 /*-----------------------------------------------------------------*/
6868 static void
6869 AccAXLsh (char *x, int shCount)
6870 {
6871   switch (shCount)
6872     {
6873     case 0:
6874       break;
6875     case 1:
6876       AccAXLsh1 (x);
6877       break;
6878     case 2:
6879       AccAXLsh1 (x);
6880       AccAXLsh1 (x);
6881       break;
6882     case 3:
6883     case 4:
6884     case 5:                     // AAAAABBB:CCCCCDDD
6885
6886       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
6887
6888       emitcode ("anl", "a,#0x%02x",
6889                 SLMask[shCount]);       // BBB00000:CCCCCDDD
6890
6891       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
6892
6893       AccRol (shCount);         // DDDCCCCC:BBB00000
6894
6895       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
6896
6897       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
6898
6899       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
6900
6901       emitcode ("anl", "a,#0x%02x",
6902                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
6903
6904       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
6905
6906       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
6907
6908       break;
6909     case 6:                     // AAAAAABB:CCCCCCDD
6910       emitcode ("anl", "a,#0x%02x",
6911                 SRMask[shCount]);       // 000000BB:CCCCCCDD
6912       emitcode ("mov", "c,acc.0");      // c = B
6913       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
6914 #if 0
6915       AccAXRrl1 (x);            // BCCCCCCD:D000000B
6916       AccAXRrl1 (x);            // BBCCCCCC:DD000000
6917 #else
6918       emitcode("rrc","a"); 
6919       emitcode("xch","a,%s", x); 
6920       emitcode("rrc","a"); 
6921       emitcode("mov","c,acc.0"); //<< get correct bit 
6922       emitcode("xch","a,%s", x); 
6923
6924       emitcode("rrc","a"); 
6925       emitcode("xch","a,%s", x); 
6926       emitcode("rrc","a"); 
6927       emitcode("xch","a,%s", x); 
6928 #endif
6929       break;
6930     case 7:                     // a:x <<= 7
6931
6932       emitcode ("anl", "a,#0x%02x",
6933                 SRMask[shCount]);       // 0000000B:CCCCCCCD
6934
6935       emitcode ("mov", "c,acc.0");      // c = B
6936
6937       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
6938
6939       AccAXRrl1 (x);            // BCCCCCCC:D0000000
6940
6941       break;
6942     default:
6943       break;
6944     }
6945 }
6946 #endif
6947
6948 #ifdef BETTER_LITERAL_SHIFT
6949 //REMOVE ME!!!
6950 /*-----------------------------------------------------------------*/
6951 /* AccAXRsh - right shift a:x known count (0..7)                   */
6952 /*-----------------------------------------------------------------*/
6953 static void
6954 AccAXRsh (char *x, int shCount)
6955 {
6956   switch (shCount)
6957     {
6958     case 0:
6959       break;
6960     case 1:
6961       CLRC;
6962       AccAXRrl1 (x);            // 0->a:x
6963
6964       break;
6965     case 2:
6966       CLRC;
6967       AccAXRrl1 (x);            // 0->a:x
6968
6969       CLRC;
6970       AccAXRrl1 (x);            // 0->a:x
6971
6972       break;
6973     case 3:
6974     case 4:
6975     case 5:                     // AAAAABBB:CCCCCDDD = a:x
6976
6977       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
6978
6979       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
6980
6981       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
6982
6983       emitcode ("anl", "a,#0x%02x",
6984                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
6985
6986       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
6987
6988       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
6989
6990       emitcode ("anl", "a,#0x%02x",
6991                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
6992
6993       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
6994
6995       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
6996
6997       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
6998
6999       break;
7000     case 6:                     // AABBBBBB:CCDDDDDD
7001
7002       emitcode ("mov", "c,acc.7");
7003       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7004
7005       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7006
7007       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7008
7009       emitcode ("anl", "a,#0x%02x",
7010                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7011
7012       break;
7013     case 7:                     // ABBBBBBB:CDDDDDDD
7014
7015       emitcode ("mov", "c,acc.7");      // c = A
7016
7017       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7018
7019       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7020
7021       emitcode ("anl", "a,#0x%02x",
7022                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7023
7024       break;
7025     default:
7026       break;
7027     }
7028 }
7029 #endif
7030
7031 #ifdef BETTER_LITERAL_SHIFT
7032 /*-----------------------------------------------------------------*/
7033 /* AccAXRshS - right shift signed a:x known count (0..7)           */
7034 /*-----------------------------------------------------------------*/
7035 static void
7036 AccAXRshS (char *x, int shCount)
7037 {
7038   symbol *tlbl;
7039   switch (shCount)
7040     {
7041     case 0:
7042       break;
7043     case 1:
7044       emitcode ("mov", "c,acc.7");
7045       AccAXRrl1 (x);            // s->a:x
7046
7047       break;
7048     case 2:
7049       emitcode ("mov", "c,acc.7");
7050       AccAXRrl1 (x);            // s->a:x
7051
7052       emitcode ("mov", "c,acc.7");
7053       AccAXRrl1 (x);            // s->a:x
7054
7055       break;
7056     case 3:
7057     case 4:
7058     case 5:                     // AAAAABBB:CCCCCDDD = a:x
7059
7060       tlbl = newiTempLabel (NULL);
7061       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
7062
7063       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
7064
7065       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
7066
7067       emitcode ("anl", "a,#0x%02x",
7068                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
7069
7070       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
7071
7072       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
7073
7074       emitcode ("anl", "a,#0x%02x",
7075                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
7076
7077       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
7078
7079       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
7080
7081       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
7082
7083       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7084       emitcode ("orl", "a,#0x%02x",
7085                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
7086
7087       emitcode ("", "%05d$:", tlbl->key + 100);
7088       break;                    // SSSSAAAA:BBBCCCCC
7089
7090     case 6:                     // AABBBBBB:CCDDDDDD
7091
7092       tlbl = newiTempLabel (NULL);
7093       emitcode ("mov", "c,acc.7");
7094       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
7095
7096       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
7097
7098       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
7099
7100       emitcode ("anl", "a,#0x%02x",
7101                 SRMask[shCount]);       // 000000AA:BBBBBBCC
7102
7103       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7104       emitcode ("orl", "a,#0x%02x",
7105                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
7106
7107       emitcode ("", "%05d$:", tlbl->key + 100);
7108       break;
7109     case 7:                     // ABBBBBBB:CDDDDDDD
7110
7111       tlbl = newiTempLabel (NULL);
7112       emitcode ("mov", "c,acc.7");      // c = A
7113
7114       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
7115
7116       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
7117
7118       emitcode ("anl", "a,#0x%02x",
7119                 SRMask[shCount]);       // 0000000A:BBBBBBBC
7120
7121       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7122       emitcode ("orl", "a,#0x%02x",
7123                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
7124
7125       emitcode ("", "%05d$:", tlbl->key + 100);
7126       break;
7127     default:
7128       break;
7129     }
7130 }
7131 #endif
7132
7133 #ifdef BETTER_LITERAL_SHIFT
7134 static void
7135 _loadLeftIntoAx(char    **lsb, 
7136                 operand *left, 
7137                 operand *result,
7138                 int     offl,
7139                 int     offr)
7140 {
7141   // Get the initial value from left into a pair of registers.
7142   // MSB must be in A, LSB can be any register.
7143   //
7144   // If the result is held in registers, it is an optimization
7145   // if the LSB can be held in the register which will hold the,
7146   // result LSB since this saves us from having to copy it into
7147   // the result following AccAXLsh.
7148   //
7149   // If the result is addressed indirectly, this is not a gain.
7150   if (AOP_NEEDSACC(result))
7151   {
7152        char *leftByte;
7153        
7154        _startLazyDPSEvaluation();
7155       if (AOP_TYPE(left) == AOP_DPTR2)
7156        {
7157            // Get MSB in A.
7158            MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE));
7159            // get LSB in DP2_RESULT_REG.
7160            leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE);
7161            assert(!strcmp(leftByte, DP2_RESULT_REG));
7162        }
7163        else
7164        {
7165            // get LSB into DP2_RESULT_REG
7166            leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE);
7167            if (strcmp(leftByte, DP2_RESULT_REG))
7168            {
7169                TR_AP("#7");
7170                emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7171            }
7172            // And MSB in A.
7173            leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE);
7174            assert(strcmp(leftByte, DP2_RESULT_REG));
7175            MOVA(leftByte);
7176        }
7177        _endLazyDPSEvaluation();
7178        *lsb = DP2_RESULT_REG;
7179   }
7180   else
7181   {
7182       if (sameRegs (AOP (result), AOP (left)) &&
7183         ((offl + MSB16) == offr))
7184       {
7185           /* don't crash result[offr] */
7186           MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE));
7187           emitcode ("xch", "a,%s", 
7188                     aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE));
7189       }
7190       else
7191       {
7192           movLeft2Result (left, offl, result, offr, 0);
7193           MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE));
7194       }
7195       *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE);
7196       assert(strcmp(*lsb,"a"));      
7197   }
7198 }
7199
7200 static void
7201 _storeAxResults(char    *lsb,
7202                 operand *result,
7203                 int     offr)
7204 {
7205   _startLazyDPSEvaluation();
7206   if (AOP_NEEDSACC(result))
7207   {
7208       /* We have to explicitly update the result LSB.
7209        */
7210       emitcode("xch","a,%s", lsb);
7211       aopPut(AOP(result), "a", offr);
7212       emitcode("mov","a,%s", lsb);
7213   }
7214   if (getDataSize (result) > 1)
7215   {
7216       aopPut (AOP (result), "a", offr + MSB16);
7217   }
7218   _endLazyDPSEvaluation();
7219 }
7220
7221 /*-----------------------------------------------------------------*/
7222 /* shiftL2Left2Result - shift left two bytes from left to result   */
7223 /*-----------------------------------------------------------------*/
7224 static void
7225 shiftL2Left2Result (operand * left, int offl,
7226                     operand * result, int offr, int shCount)
7227 {
7228   char *lsb;
7229
7230   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7231   
7232   AccAXLsh (lsb, shCount);
7233   
7234   _storeAxResults(lsb, result, offr);
7235 }
7236 #endif
7237
7238 #ifdef BETTER_LITERAL_SHIFT
7239 /*-----------------------------------------------------------------*/
7240 /* shiftR2Left2Result - shift right two bytes from left to result  */
7241 /*-----------------------------------------------------------------*/
7242 static void
7243 shiftR2Left2Result (operand * left, int offl,
7244                     operand * result, int offr,
7245                     int shCount, int sign)
7246 {
7247   char *lsb;
7248   
7249   _loadLeftIntoAx(&lsb, left, result, offl, offr);
7250   
7251   /* a:x >> shCount (x = lsb(result)) */
7252   if (sign)
7253   {
7254      AccAXRshS(lsb, shCount);
7255   }
7256   else
7257   {
7258     AccAXRsh(lsb, shCount);
7259   }
7260   
7261   _storeAxResults(lsb, result, offr);
7262 }
7263 #endif
7264
7265 #if 0
7266 //REMOVE ME!!!
7267 /*-----------------------------------------------------------------*/
7268 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7269 /*-----------------------------------------------------------------*/
7270 static void
7271 shiftLLeftOrResult (operand * left, int offl,
7272                     operand * result, int offr, int shCount)
7273 {
7274   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7275   /* shift left accumulator */
7276   AccLsh (shCount);
7277   /* or with result */
7278   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7279   /* back to result */
7280   aopPut (AOP (result), "a", offr);
7281 }
7282 #endif
7283
7284 #if 0
7285 //REMOVE ME!!!
7286 /*-----------------------------------------------------------------*/
7287 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7288 /*-----------------------------------------------------------------*/
7289 static void
7290 shiftRLeftOrResult (operand * left, int offl,
7291                     operand * result, int offr, int shCount)
7292 {
7293   MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE));
7294   /* shift right accumulator */
7295   AccRsh (shCount);
7296   /* or with result */
7297   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE));
7298   /* back to result */
7299   aopPut (AOP (result), "a", offr);
7300 }
7301 #endif
7302
7303 #ifdef BETTER_LITERAL_SHIFT
7304 /*-----------------------------------------------------------------*/
7305 /* genlshOne - left shift a one byte quantity by known count       */
7306 /*-----------------------------------------------------------------*/
7307 static void
7308 genlshOne (operand * result, operand * left, int shCount)
7309 {
7310   D (emitcode (";", "genlshOne "););
7311   shiftL1Left2Result (left, LSB, result, LSB, shCount);
7312 }
7313 #endif
7314
7315 #ifdef BETTER_LITERAL_SHIFT
7316 /*-----------------------------------------------------------------*/
7317 /* genlshTwo - left shift two bytes by known amount != 0           */
7318 /*-----------------------------------------------------------------*/
7319 static void
7320 genlshTwo (operand * result, operand * left, int shCount)
7321 {
7322   int size;
7323
7324   D (emitcode (";", "genlshTwo "););
7325
7326   size = getDataSize (result);
7327
7328   /* if shCount >= 8 */
7329   if (shCount >= 8)
7330   {
7331       shCount -= 8;
7332
7333       _startLazyDPSEvaluation();
7334
7335       if (size > 1)
7336         {
7337           if (shCount)
7338           {
7339             _endLazyDPSEvaluation();
7340             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7341             aopPut (AOP (result), zero, LSB);       
7342           }
7343           else
7344           {
7345             movLeft2Result (left, LSB, result, MSB16, 0);
7346             aopPut (AOP (result), zero, LSB);
7347             _endLazyDPSEvaluation();
7348           }
7349         }
7350         else
7351         {
7352           aopPut (AOP (result), zero, LSB);
7353           _endLazyDPSEvaluation();
7354         }
7355   }
7356
7357   /*  1 <= shCount <= 7 */
7358   else
7359     {
7360       if (size == 1)
7361       {
7362         shiftL1Left2Result (left, LSB, result, LSB, shCount);
7363       }
7364       else
7365       {
7366         shiftL2Left2Result (left, LSB, result, LSB, shCount);
7367       }
7368     }
7369 }
7370 #endif
7371
7372 #if 0
7373 //REMOVE ME!!!
7374 /*-----------------------------------------------------------------*/
7375 /* shiftLLong - shift left one long from left to result            */
7376 /* offl = LSB or MSB16                                             */
7377 /*-----------------------------------------------------------------*/
7378 static void
7379 shiftLLong (operand * left, operand * result, int offr)
7380 {
7381   char *l;
7382   int size = AOP_SIZE (result);
7383
7384   if (size >= LSB + offr)
7385     {
7386       l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE);
7387       MOVA (l);
7388       emitcode ("add", "a,acc");
7389       if (sameRegs (AOP (left), AOP (result)) &&
7390           size >= MSB16 + offr && offr != LSB)
7391         emitcode ("xch", "a,%s",
7392                   aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE));
7393       else
7394         aopPut (AOP (result), "a", LSB + offr);
7395     }
7396
7397   if (size >= MSB16 + offr)
7398     {
7399       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7400         {
7401           l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE);
7402           MOVA (l);
7403         }
7404       emitcode ("rlc", "a");
7405       if (sameRegs (AOP (left), AOP (result)) &&
7406           size >= MSB24 + offr && offr != LSB)
7407         emitcode ("xch", "a,%s",
7408                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE));
7409       else
7410         aopPut (AOP (result), "a", MSB16 + offr);
7411     }
7412
7413   if (size >= MSB24 + offr)
7414     {
7415       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7416         {
7417           l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE);
7418           MOVA (l);
7419         }
7420       emitcode ("rlc", "a");
7421       if (sameRegs (AOP (left), AOP (result)) &&
7422           size >= MSB32 + offr && offr != LSB)
7423         emitcode ("xch", "a,%s",
7424                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE));
7425       else
7426         aopPut (AOP (result), "a", MSB24 + offr);
7427     }
7428
7429   if (size > MSB32 + offr)
7430     {
7431       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7432         {
7433           l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE);
7434           MOVA (l);
7435         }
7436       emitcode ("rlc", "a");
7437       aopPut (AOP (result), "a", MSB32 + offr);
7438     }
7439   if (offr != LSB)
7440     aopPut (AOP (result), zero, LSB);
7441 }
7442 #endif
7443
7444 #if 0
7445 //REMOVE ME!!!
7446 /*-----------------------------------------------------------------*/
7447 /* genlshFour - shift four byte by a known amount != 0             */
7448 /*-----------------------------------------------------------------*/
7449 static void
7450 genlshFour (operand * result, operand * left, int shCount)
7451 {
7452   int size;
7453
7454   D (emitcode (";", "genlshFour ");
7455     );
7456
7457   size = AOP_SIZE (result);
7458
7459   /* if shifting more that 3 bytes */
7460   if (shCount >= 24)
7461     {
7462       shCount -= 24;
7463       if (shCount)
7464         /* lowest order of left goes to the highest
7465            order of the destination */
7466         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7467       else
7468         movLeft2Result (left, LSB, result, MSB32, 0);
7469       aopPut (AOP (result), zero, LSB);
7470       aopPut (AOP (result), zero, MSB16);
7471       aopPut (AOP (result), zero, MSB24);
7472       return;
7473     }
7474
7475   /* more than two bytes */
7476   else if (shCount >= 16)
7477     {
7478       /* lower order two bytes goes to higher order two bytes */
7479       shCount -= 16;
7480       /* if some more remaining */
7481       if (shCount)
7482         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7483       else
7484         {
7485           movLeft2Result (left, MSB16, result, MSB32, 0);
7486           movLeft2Result (left, LSB, result, MSB24, 0);
7487         }
7488       aopPut (AOP (result), zero, MSB16);
7489       aopPut (AOP (result), zero, LSB);
7490       return;
7491     }
7492
7493   /* if more than 1 byte */
7494   else if (shCount >= 8)
7495     {
7496       /* lower order three bytes goes to higher order  three bytes */
7497       shCount -= 8;
7498       if (size == 2)
7499         {
7500           if (shCount)
7501             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7502           else
7503             movLeft2Result (left, LSB, result, MSB16, 0);
7504         }
7505       else
7506         {                       /* size = 4 */
7507           if (shCount == 0)
7508             {
7509               movLeft2Result (left, MSB24, result, MSB32, 0);
7510               movLeft2Result (left, MSB16, result, MSB24, 0);
7511               movLeft2Result (left, LSB, result, MSB16, 0);
7512               aopPut (AOP (result), zero, LSB);
7513             }
7514           else if (shCount == 1)
7515             shiftLLong (left, result, MSB16);
7516           else
7517             {
7518               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7519               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7520               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7521               aopPut (AOP (result), zero, LSB);
7522             }
7523         }
7524     }
7525
7526   /* 1 <= shCount <= 7 */
7527   else if (shCount <= 2)
7528     {
7529       shiftLLong (left, result, LSB);
7530       if (shCount == 2)
7531         shiftLLong (result, result, LSB);
7532     }
7533   /* 3 <= shCount <= 7, optimize */
7534   else
7535     {
7536       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7537       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7538       shiftL2Left2Result (left, LSB, result, LSB, shCount);
7539     }
7540 }
7541 #endif
7542
7543 #ifdef BETTER_LITERAL_SHIFT
7544 /*-----------------------------------------------------------------*/
7545 /* genLeftShiftLiteral - left shifting by known count              */
7546 /*-----------------------------------------------------------------*/
7547 static bool
7548 genLeftShiftLiteral (operand * left,
7549                      operand * right,
7550                      operand * result,
7551                      iCode * ic)
7552 {
7553   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7554   int size;
7555
7556   size = getSize (operandType (result));
7557
7558   D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
7559
7560   /* We only handle certain easy cases so far. */
7561   if ((shCount != 0)
7562    && (shCount < (size * 8))
7563    && (size != 1)
7564    && (size != 2))
7565   {
7566       D(emitcode (";", "genLeftShiftLiteral wimping out"););    
7567       return FALSE;
7568   }
7569
7570   freeAsmop (right, NULL, ic, TRUE);
7571
7572   aopOp(left, ic, FALSE, FALSE);
7573   aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR));
7574
7575 #if 1 // debug spew
7576   if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
7577   {
7578         emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
7579         if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
7580         {
7581            emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
7582         }
7583   }
7584   if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
7585   {
7586         emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
7587         if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
7588         {
7589            emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
7590         }       
7591   }  
7592 #endif
7593   
7594 #if VIEW_SIZE
7595   emitcode ("; shift left ", "result %d, left %d", size,
7596             AOP_SIZE (left));
7597 #endif
7598
7599   /* I suppose that the left size >= result size */
7600   if (shCount == 0)
7601   {
7602         _startLazyDPSEvaluation();
7603         while (size--)
7604         {
7605           movLeft2Result (left, size, result, size, 0);
7606         }
7607         _endLazyDPSEvaluation();
7608   }
7609   else if (shCount >= (size * 8))
7610   {
7611     _startLazyDPSEvaluation();
7612     while (size--)
7613     {
7614       aopPut (AOP (result), zero, size);
7615     }
7616     _endLazyDPSEvaluation();
7617   }
7618   else
7619   {
7620       switch (size)
7621         {
7622         case 1:
7623           genlshOne (result, left, shCount);
7624           break;
7625
7626         case 2:
7627           genlshTwo (result, left, shCount);
7628           break;
7629 #if 0
7630         case 4:
7631           genlshFour (result, left, shCount);
7632           break;
7633 #endif
7634         default:
7635           fprintf(stderr, "*** ack! mystery literal shift!\n");   
7636           break;
7637         }
7638     }
7639   freeAsmop (left, NULL, ic, TRUE);
7640   freeAsmop (result, NULL, ic, TRUE);
7641   return TRUE;
7642 }
7643 #endif
7644
7645 /*-----------------------------------------------------------------*/
7646 /* genLeftShift - generates code for left shifting                 */
7647 /*-----------------------------------------------------------------*/
7648 static void
7649 genLeftShift (iCode * ic)
7650 {
7651   operand *left, *right, *result;
7652   int size, offset;
7653   char *l;
7654   symbol *tlbl, *tlbl1;
7655
7656   D (emitcode (";", "genLeftShift "););
7657
7658   right = IC_RIGHT (ic);
7659   left = IC_LEFT (ic);
7660   result = IC_RESULT (ic);
7661
7662   aopOp (right, ic, FALSE, FALSE);
7663
7664
7665 #ifdef BETTER_LITERAL_SHIFT
7666   /* if the shift count is known then do it
7667      as efficiently as possible */
7668   if (AOP_TYPE (right) == AOP_LIT)
7669     {
7670       if (genLeftShiftLiteral (left, right, result, ic))
7671       {
7672         return;
7673       }
7674     }
7675 #endif
7676
7677   /* shift count is unknown then we have to form
7678      a loop get the loop count in B : Note: we take
7679      only the lower order byte since shifting
7680      more that 32 bits make no sense anyway, ( the
7681      largest size of an object can be only 32 bits ) */
7682
7683   if (AOP_TYPE (right) == AOP_LIT)
7684   {
7685       /* Really should be handled by genLeftShiftLiteral,
7686        * but since I'm too lazy to fix that today, at least we can make
7687        * some small improvement.
7688        */
7689        emitcode("mov", "b,#0x%02x",
7690                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
7691   }
7692   else
7693   {
7694         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
7695         emitcode ("inc", "b");
7696   }
7697   freeAsmop (right, NULL, ic, TRUE);
7698   aopOp (left, ic, FALSE, FALSE);
7699   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7700
7701   /* now move the left to the result if they are not the
7702      same */
7703   if (!sameRegs (AOP (left), AOP (result)) &&
7704       AOP_SIZE (result) > 1)
7705     {
7706
7707       size = AOP_SIZE (result);
7708       offset = 0;
7709       _startLazyDPSEvaluation ();
7710       while (size--)
7711         {
7712           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
7713           if (*l == '@' && (IS_AOP_PREG (result)))
7714             {
7715
7716               emitcode ("mov", "a,%s", l);
7717               aopPut (AOP (result), "a", offset);
7718             }
7719           else
7720             aopPut (AOP (result), l, offset);
7721           offset++;
7722         }
7723       _endLazyDPSEvaluation ();
7724     }
7725
7726   tlbl = newiTempLabel (NULL);
7727   size = AOP_SIZE (result);
7728   offset = 0;
7729   tlbl1 = newiTempLabel (NULL);
7730
7731   /* if it is only one byte then */
7732   if (size == 1)
7733     {
7734       symbol *tlbl1 = newiTempLabel (NULL);
7735
7736       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
7737       MOVA (l);
7738       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7739       emitcode ("", "%05d$:", tlbl->key + 100);
7740       emitcode ("add", "a,acc");
7741       emitcode ("", "%05d$:", tlbl1->key + 100);
7742       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7743       aopPut (AOP (result), "a", 0);
7744       goto release;
7745     }
7746
7747   reAdjustPreg (AOP (result));
7748
7749   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7750   emitcode ("", "%05d$:", tlbl->key + 100);
7751   l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7752   MOVA (l);
7753   emitcode ("add", "a,acc");
7754   aopPut (AOP (result), "a", offset++);
7755   _startLazyDPSEvaluation ();
7756   while (--size)
7757     {
7758       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
7759       MOVA (l);
7760       emitcode ("rlc", "a");
7761       aopPut (AOP (result), "a", offset++);
7762     }
7763   _endLazyDPSEvaluation ();
7764   reAdjustPreg (AOP (result));
7765
7766   emitcode ("", "%05d$:", tlbl1->key + 100);
7767   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7768 release:
7769   freeAsmop (left, NULL, ic, TRUE);
7770   freeAsmop (result, NULL, ic, TRUE);
7771 }
7772
7773 #ifdef BETTER_LITERAL_SHIFT
7774 /*-----------------------------------------------------------------*/
7775 /* genrshOne - right shift a one byte quantity by known count      */
7776 /*-----------------------------------------------------------------*/
7777 static void
7778 genrshOne (operand * result, operand * left,
7779            int shCount, int sign)
7780 {
7781   D (emitcode (";", "genrshOne"););
7782   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7783 }
7784 #endif
7785
7786 #ifdef BETTER_LITERAL_SHIFT
7787 /*-----------------------------------------------------------------*/
7788 /* genrshTwo - right shift two bytes by known amount != 0          */
7789 /*-----------------------------------------------------------------*/
7790 static void
7791 genrshTwo (operand * result, operand * left,
7792            int shCount, int sign)
7793 {
7794   D (emitcode (";", "genrshTwo"););
7795
7796   /* if shCount >= 8 */
7797   if (shCount >= 8)
7798     {
7799       shCount -= 8;
7800       _startLazyDPSEvaluation();
7801       if (shCount)
7802       {
7803         shiftR1Left2Result (left, MSB16, result, LSB,
7804                             shCount, sign);
7805       }                     
7806       else
7807       {
7808         movLeft2Result (left, MSB16, result, LSB, sign);
7809       }
7810       addSign (result, MSB16, sign);
7811       _endLazyDPSEvaluation();
7812     }
7813
7814   /*  1 <= shCount <= 7 */
7815   else
7816   {
7817     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7818   }
7819 }
7820 #endif
7821
7822 #if 0
7823 //REMOVE ME!!!
7824 /*-----------------------------------------------------------------*/
7825 /* shiftRLong - shift right one long from left to result           */
7826 /* offl = LSB or MSB16                                             */
7827 /*-----------------------------------------------------------------*/
7828 static void
7829 shiftRLong (operand * left, int offl,
7830             operand * result, int sign)
7831 {
7832   int isSameRegs=sameRegs(AOP(left),AOP(result));
7833
7834   if (isSameRegs && offl>1) {
7835     // we are in big trouble, but this shouldn't happen
7836     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7837   }
7838
7839   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7840   
7841   if (offl==MSB16) {
7842     // shift is > 8
7843     if (sign) {
7844       emitcode ("rlc", "a");
7845       emitcode ("subb", "a,acc");
7846       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7847     } else {
7848       aopPut (AOP(result), zero, MSB32);
7849     }
7850   }
7851
7852   if (!sign) {
7853     emitcode ("clr", "c");
7854   } else {
7855     emitcode ("mov", "c,acc.7");
7856   }
7857
7858   emitcode ("rrc", "a");
7859
7860   if (isSameRegs && offl==MSB16) {
7861     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7862   } else {
7863     aopPut (AOP (result), "a", MSB32);
7864     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7865   }
7866
7867   emitcode ("rrc", "a");
7868   if (isSameRegs && offl==1) {
7869     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7870   } else {
7871     aopPut (AOP (result), "a", MSB24);
7872     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7873   }
7874   emitcode ("rrc", "a");
7875   aopPut (AOP (result), "a", MSB16 - offl);
7876
7877   if (offl == LSB)
7878     {
7879       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7880       emitcode ("rrc", "a");
7881       aopPut (AOP (result), "a", LSB);
7882     }
7883 }
7884 #endif
7885
7886 #if 0
7887 //REMOVE ME!!!
7888 /*-----------------------------------------------------------------*/
7889 /* genrshFour - shift four byte by a known amount != 0             */
7890 /*-----------------------------------------------------------------*/
7891 static void
7892 genrshFour (operand * result, operand * left,
7893             int shCount, int sign)
7894 {
7895   D (emitcode (";", "genrshFour");
7896     );
7897
7898   /* if shifting more that 3 bytes */
7899   if (shCount >= 24)
7900     {
7901       shCount -= 24;
7902       if (shCount)
7903         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7904       else
7905         movLeft2Result (left, MSB32, result, LSB, sign);
7906       addSign (result, MSB16, sign);
7907     }
7908   else if (shCount >= 16)
7909     {
7910       shCount -= 16;
7911       if (shCount)
7912         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7913       else
7914         {
7915           movLeft2Result (left, MSB24, result, LSB, 0);
7916           movLeft2Result (left, MSB32, result, MSB16, sign);
7917         }
7918       addSign (result, MSB24, sign);
7919     }
7920   else if (shCount >= 8)
7921     {
7922       shCount -= 8;
7923       if (shCount == 1)
7924         shiftRLong (left, MSB16, result, sign);
7925       else if (shCount == 0)
7926         {
7927           movLeft2Result (left, MSB16, result, LSB, 0);
7928           movLeft2Result (left, MSB24, result, MSB16, 0);
7929           movLeft2Result (left, MSB32, result, MSB24, sign);
7930           addSign (result, MSB32, sign);
7931         }
7932       else
7933         {
7934           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7935           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7936           /* the last shift is signed */
7937           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7938           addSign (result, MSB32, sign);
7939         }
7940     }
7941   else
7942     {                           /* 1 <= shCount <= 7 */
7943       if (shCount <= 2)
7944         {
7945           shiftRLong (left, LSB, result, sign);
7946           if (shCount == 2)
7947             shiftRLong (result, LSB, result, sign);
7948         }
7949       else
7950         {
7951           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7952           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7953           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7954         }
7955     }
7956 }
7957 #endif
7958
7959 #ifdef BETTER_LITERAL_SHIFT
7960 /*-----------------------------------------------------------------*/
7961 /* genRightShiftLiteral - right shifting by known count            */
7962 /*-----------------------------------------------------------------*/
7963 static bool
7964 genRightShiftLiteral (operand * left,
7965                       operand * right,
7966                       operand * result,
7967                       iCode * ic,
7968                       int sign)
7969 {
7970   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7971   int size;
7972
7973   size = getSize (operandType (result));
7974
7975   D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
7976
7977   /* We only handle certain easy cases so far. */
7978   if ((shCount != 0)
7979    && (shCount < (size * 8))
7980    && (size != 1)
7981    && (size != 2))
7982   {
7983       D(emitcode (";", "genRightShiftLiteral wimping out"););   
7984       return FALSE;
7985   }
7986
7987   freeAsmop (right, NULL, ic, TRUE);
7988
7989   aopOp (left, ic, FALSE, FALSE);
7990   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
7991
7992 #if VIEW_SIZE
7993   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7994             AOP_SIZE (left));
7995 #endif
7996
7997   /* test the LEFT size !!! */
7998
7999   /* I suppose that the left size >= result size */
8000   if (shCount == 0)
8001   {
8002       size = getDataSize (result);
8003       _startLazyDPSEvaluation();
8004       while (size--)
8005       {
8006         movLeft2Result (left, size, result, size, 0);
8007       }
8008       _endLazyDPSEvaluation();
8009   }
8010   else if (shCount >= (size * 8))
8011     {
8012       if (sign)
8013       {
8014         /* get sign in acc.7 */
8015         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE));
8016       }
8017       addSign (result, LSB, sign);
8018     }
8019   else
8020     {
8021       switch (size)
8022         {
8023         case 1:
8024           genrshOne (result, left, shCount, sign);
8025           break;
8026
8027         case 2:
8028           genrshTwo (result, left, shCount, sign);
8029           break;
8030 #if 0
8031         case 4:
8032           genrshFour (result, left, shCount, sign);
8033           break;
8034 #endif    
8035         default:
8036           break;
8037         }
8038
8039       freeAsmop (left, NULL, ic, TRUE);
8040       freeAsmop (result, NULL, ic, TRUE);
8041     }
8042     return TRUE;
8043 }
8044 #endif
8045
8046 /*-----------------------------------------------------------------*/
8047 /* genSignedRightShift - right shift of signed number              */
8048 /*-----------------------------------------------------------------*/
8049 static void
8050 genSignedRightShift (iCode * ic)
8051 {
8052   operand *right, *left, *result;
8053   int size, offset;
8054   char *l;
8055   symbol *tlbl, *tlbl1;
8056
8057   D (emitcode (";", "genSignedRightShift "););
8058
8059   /* we do it the hard way put the shift count in b
8060      and loop thru preserving the sign */
8061
8062   right = IC_RIGHT (ic);
8063   left = IC_LEFT (ic);
8064   result = IC_RESULT (ic);
8065
8066   aopOp (right, ic, FALSE, FALSE);
8067
8068 #ifdef BETTER_LITERAL_SHIFT
8069   if (AOP_TYPE (right) == AOP_LIT)
8070     {
8071       if (genRightShiftLiteral (left, right, result, ic, 1))
8072       {
8073         return;
8074       }
8075     }
8076 #endif
8077   /* shift count is unknown then we have to form
8078      a loop get the loop count in B : Note: we take
8079      only the lower order byte since shifting
8080      more that 32 bits make no sense anyway, ( the
8081      largest size of an object can be only 32 bits ) */
8082
8083   if (AOP_TYPE (right) == AOP_LIT)
8084   {
8085       /* Really should be handled by genRightShiftLiteral,
8086        * but since I'm too lazy to fix that today, at least we can make
8087        * some small improvement.
8088        */
8089        emitcode("mov", "b,#0x%02x",
8090                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8091   }
8092   else
8093   {
8094         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8095         emitcode ("inc", "b");
8096   }
8097   freeAsmop (right, NULL, ic, TRUE);
8098   aopOp (left, ic, FALSE, FALSE);
8099   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8100
8101   /* now move the left to the result if they are not the
8102      same */
8103   if (!sameRegs (AOP (left), AOP (result)) &&
8104       AOP_SIZE (result) > 1)
8105     {
8106
8107       size = AOP_SIZE (result);
8108       offset = 0;
8109       _startLazyDPSEvaluation ();
8110       while (size--)
8111         {
8112           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8113           if (*l == '@' && IS_AOP_PREG (result))
8114             {
8115
8116               emitcode ("mov", "a,%s", l);
8117               aopPut (AOP (result), "a", offset);
8118             }
8119           else
8120             aopPut (AOP (result), l, offset);
8121           offset++;
8122         }
8123       _endLazyDPSEvaluation ();
8124     }
8125
8126   /* mov the highest order bit to OVR */
8127   tlbl = newiTempLabel (NULL);
8128   tlbl1 = newiTempLabel (NULL);
8129
8130   size = AOP_SIZE (result);
8131   offset = size - 1;
8132   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
8133   emitcode ("rlc", "a");
8134   emitcode ("mov", "ov,c");
8135   /* if it is only one byte then */
8136   if (size == 1)
8137     {
8138       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8139       MOVA (l);
8140       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8141       emitcode ("", "%05d$:", tlbl->key + 100);
8142       emitcode ("mov", "c,ov");
8143       emitcode ("rrc", "a");
8144       emitcode ("", "%05d$:", tlbl1->key + 100);
8145       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8146       aopPut (AOP (result), "a", 0);
8147       goto release;
8148     }
8149
8150   reAdjustPreg (AOP (result));
8151   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8152   emitcode ("", "%05d$:", tlbl->key + 100);
8153   emitcode ("mov", "c,ov");
8154   _startLazyDPSEvaluation ();
8155   while (size--)
8156     {
8157       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8158       MOVA (l);
8159       emitcode ("rrc", "a");
8160       aopPut (AOP (result), "a", offset--);
8161     }
8162   _endLazyDPSEvaluation ();
8163   reAdjustPreg (AOP (result));
8164   emitcode ("", "%05d$:", tlbl1->key + 100);
8165   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8166
8167 release:
8168   freeAsmop (left, NULL, ic, TRUE);
8169   freeAsmop (result, NULL, ic, TRUE);
8170 }
8171
8172 /*-----------------------------------------------------------------*/
8173 /* genRightShift - generate code for right shifting                */
8174 /*-----------------------------------------------------------------*/
8175 static void
8176 genRightShift (iCode * ic)
8177 {
8178   operand *right, *left, *result;
8179   sym_link *retype;
8180   int size, offset;
8181   char *l;
8182   symbol *tlbl, *tlbl1;
8183
8184   D (emitcode (";", "genRightShift "););
8185
8186   /* if signed then we do it the hard way preserve the
8187      sign bit moving it inwards */
8188   retype = getSpec (operandType (IC_RESULT (ic)));
8189
8190   if (!SPEC_USIGN (retype))
8191     {
8192       genSignedRightShift (ic);
8193       return;
8194     }
8195
8196   /* signed & unsigned types are treated the same : i.e. the
8197      signed is NOT propagated inwards : quoting from the
8198      ANSI - standard : "for E1 >> E2, is equivalent to division
8199      by 2**E2 if unsigned or if it has a non-negative value,
8200      otherwise the result is implementation defined ", MY definition
8201      is that the sign does not get propagated */
8202
8203   right = IC_RIGHT (ic);
8204   left = IC_LEFT (ic);
8205   result = IC_RESULT (ic);
8206
8207   aopOp (right, ic, FALSE, FALSE);
8208
8209 #ifdef BETTER_LITERAL_SHIFT
8210   /* if the shift count is known then do it
8211      as efficiently as possible */
8212   if (AOP_TYPE (right) == AOP_LIT)
8213     {
8214       if (genRightShiftLiteral (left, right, result, ic, 0))
8215       {
8216         return;
8217       }
8218     }
8219 #endif
8220
8221   /* shift count is unknown then we have to form
8222      a loop get the loop count in B : Note: we take
8223      only the lower order byte since shifting
8224      more that 32 bits make no sense anyway, ( the
8225      largest size of an object can be only 32 bits ) */
8226   
8227   if (AOP_TYPE (right) == AOP_LIT)
8228   {
8229       /* Really should be handled by genRightShiftLiteral,
8230        * but since I'm too lazy to fix that today, at least we can make
8231        * some small improvement.
8232        */
8233        emitcode("mov", "b,#0x%02x",
8234                 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8235   }
8236   else
8237   {
8238         emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
8239         emitcode ("inc", "b");
8240   }
8241   freeAsmop (right, NULL, ic, TRUE);
8242   aopOp (left, ic, FALSE, FALSE);
8243   aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR);
8244
8245   /* now move the left to the result if they are not the
8246      same */
8247   if (!sameRegs (AOP (left), AOP (result)) &&
8248       AOP_SIZE (result) > 1)
8249     {
8250
8251       size = AOP_SIZE (result);
8252       offset = 0;
8253       _startLazyDPSEvaluation ();
8254       while (size--)
8255         {
8256           l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE);
8257           if (*l == '@' && IS_AOP_PREG (result))
8258             {
8259
8260               emitcode ("mov", "a,%s", l);
8261               aopPut (AOP (result), "a", offset);
8262             }
8263           else
8264             aopPut (AOP (result), l, offset);
8265           offset++;
8266         }
8267       _endLazyDPSEvaluation ();
8268     }
8269
8270   tlbl = newiTempLabel (NULL);
8271   tlbl1 = newiTempLabel (NULL);
8272   size = AOP_SIZE (result);
8273   offset = size - 1;
8274
8275   /* if it is only one byte then */
8276   if (size == 1)
8277     {
8278       l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE);
8279       MOVA (l);
8280       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8281       emitcode ("", "%05d$:", tlbl->key + 100);
8282       CLRC;
8283       emitcode ("rrc", "a");
8284       emitcode ("", "%05d$:", tlbl1->key + 100);
8285       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8286       aopPut (AOP (result), "a", 0);
8287       goto release;
8288     }
8289
8290   reAdjustPreg (AOP (result));
8291   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8292   emitcode ("", "%05d$:", tlbl->key + 100);
8293   CLRC;
8294   _startLazyDPSEvaluation ();
8295   while (size--)
8296     {
8297       l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE);
8298       MOVA (l);
8299       emitcode ("rrc", "a");
8300       aopPut (AOP (result), "a", offset--);
8301     }
8302   _endLazyDPSEvaluation ();
8303   reAdjustPreg (AOP (result));
8304
8305   emitcode ("", "%05d$:", tlbl1->key + 100);
8306   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8307
8308 release:
8309   freeAsmop (left, NULL, ic, TRUE);
8310   freeAsmop (result, NULL, ic, TRUE);
8311 }
8312
8313 /*-----------------------------------------------------------------*/
8314 /* genUnpackBits - generates code for unpacking bits               */
8315 /*-----------------------------------------------------------------*/
8316 static void
8317 genUnpackBits (operand * result, char *rname, int ptype)
8318 {
8319   int shCnt;
8320   int rlen = 0;
8321   sym_link *etype;
8322   int offset = 0;
8323
8324   D (emitcode (";", "genUnpackBits ");
8325     );
8326
8327   etype = getSpec (operandType (result));
8328
8329   /* read the first byte  */
8330   switch (ptype)
8331     {
8332
8333     case POINTER:
8334     case IPOINTER:
8335       emitcode ("mov", "a,@%s", rname);
8336       break;
8337
8338     case PPOINTER:
8339       emitcode ("movx", "a,@%s", rname);
8340       break;
8341
8342     case FPOINTER:
8343       emitcode ("movx", "a,@dptr");
8344       break;
8345
8346     case CPOINTER:
8347       emitcode ("clr", "a");
8348       emitcode ("movc", "a,@a+dptr");
8349       break;
8350
8351     case GPOINTER:
8352       emitcode ("lcall", "__gptrget");
8353       break;
8354     }
8355
8356   /* if we have bitdisplacement then it fits   */
8357   /* into this byte completely or if length is */
8358   /* less than a byte                          */
8359   if ((shCnt = SPEC_BSTR (etype)) ||
8360       (SPEC_BLEN (etype) <= 8))
8361     {
8362
8363       /* shift right acc */
8364       AccRsh (shCnt);
8365
8366       emitcode ("anl", "a,#0x%02x",
8367                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
8368       aopPut (AOP (result), "a", offset);
8369       return;
8370     }
8371
8372   /* bit field did not fit in a byte  */
8373   rlen = SPEC_BLEN (etype) - 8;
8374   aopPut (AOP (result), "a", offset++);
8375
8376   while (1)
8377     {
8378
8379       switch (ptype)
8380         {
8381         case POINTER:
8382         case IPOINTER:
8383           emitcode ("inc", "%s", rname);
8384           emitcode ("mov", "a,@%s", rname);
8385           break;
8386
8387         case PPOINTER:
8388           emitcode ("inc", "%s", rname);
8389           emitcode ("movx", "a,@%s", rname);
8390           break;
8391
8392         case FPOINTER:
8393           emitcode ("inc", "dptr");
8394           emitcode ("movx", "a,@dptr");
8395           break;
8396
8397         case CPOINTER:
8398           emitcode ("clr", "a");
8399           emitcode ("inc", "dptr");
8400           emitcode ("movc", "a,@a+dptr");
8401           break;
8402
8403         case GPOINTER:
8404           emitcode ("inc", "dptr");
8405           emitcode ("lcall", "__gptrget");
8406           break;
8407         }
8408
8409       rlen -= 8;
8410       /* if we are done */
8411       if (rlen < 8)
8412         break;
8413
8414       aopPut (AOP (result), "a", offset++);
8415
8416     }
8417
8418   if (rlen)
8419     {
8420       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen));
8421       aopPut (AOP (result), "a", offset);
8422     }
8423
8424   return;
8425 }
8426
8427
8428 /*-----------------------------------------------------------------*/
8429 /* genDataPointerGet - generates code when ptr offset is known     */
8430 /*-----------------------------------------------------------------*/
8431 static void
8432 genDataPointerGet (operand * left,
8433                    operand * result,
8434                    iCode * ic)
8435 {
8436   char *l;
8437   char buffer[256];
8438   int size, offset = 0;
8439   aopOp (result, ic, TRUE, FALSE);
8440
8441   /* get the string representation of the name */
8442   l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE);
8443   size = AOP_SIZE (result);
8444   _startLazyDPSEvaluation ();
8445   while (size--)
8446     {
8447       if (offset)
8448         sprintf (buffer, "(%s + %d)", l + 1, offset);
8449       else
8450         sprintf (buffer, "%s", l + 1);
8451       aopPut (AOP (result), buffer, offset++);
8452     }
8453   _endLazyDPSEvaluation ();
8454
8455   freeAsmop (left, NULL, ic, TRUE);
8456   freeAsmop (result, NULL, ic, TRUE);
8457 }
8458
8459 /*-----------------------------------------------------------------*/
8460 /* genNearPointerGet - emitcode for near pointer fetch             */
8461 /*-----------------------------------------------------------------*/
8462 static void
8463 genNearPointerGet (operand * left,
8464                    operand * result,
8465                    iCode * ic)
8466 {
8467   asmop *aop = NULL;
8468   regs *preg = NULL;
8469   char *rname;
8470   sym_link *rtype, *retype, *letype;
8471   sym_link *ltype = operandType (left);
8472   char buffer[80];
8473
8474   rtype = operandType (result);
8475   retype = getSpec (rtype);
8476   letype = getSpec (ltype);
8477
8478   aopOp (left, ic, FALSE, FALSE);
8479
8480   /* if left is rematerialisable and
8481      result is not bit variable type and
8482      the left is pointer to data space i.e
8483      lower 128 bytes of space */
8484   if (AOP_TYPE (left) == AOP_IMMD &&
8485       !IS_BITVAR (retype) &&
8486       !IS_BITVAR (letype) &&
8487       DCL_TYPE (ltype) == POINTER)
8488     {
8489       genDataPointerGet (left, result, ic);
8490       return;
8491     }
8492
8493   /* if the value is already in a pointer register
8494      then don't need anything more */
8495   if (!AOP_INPREG (AOP (left)))
8496     {
8497       /* otherwise get a free pointer register */
8498       aop = newAsmop (0);
8499       preg = getFreePtr (ic, &aop, FALSE);
8500       emitcode ("mov", "%s,%s",
8501                 preg->name,
8502                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8503       rname = preg->name;
8504     }
8505   else
8506     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8507
8508   freeAsmop (left, NULL, ic, TRUE);
8509   aopOp (result, ic, FALSE, FALSE);
8510
8511   /* if bitfield then unpack the bits */
8512   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8513     genUnpackBits (result, rname, POINTER);
8514   else
8515     {
8516       /* we have can just get the values */
8517       int size = AOP_SIZE (result);
8518       int offset = 0;
8519
8520       while (size--)
8521         {
8522           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8523             {
8524
8525               emitcode ("mov", "a,@%s", rname);
8526               aopPut (AOP (result), "a", offset);
8527             }
8528           else
8529             {
8530               sprintf (buffer, "@%s", rname);
8531               aopPut (AOP (result), buffer, offset);
8532             }
8533           offset++;
8534           if (size)
8535             emitcode ("inc", "%s", rname);
8536         }
8537     }
8538
8539   /* now some housekeeping stuff */
8540   if (aop)
8541     {
8542       /* we had to allocate for this iCode */
8543       freeAsmop (NULL, aop, ic, TRUE);
8544     }
8545   else
8546     {
8547       /* we did not allocate which means left
8548          already in a pointer register, then
8549          if size > 0 && this could be used again
8550          we have to point it back to where it
8551          belongs */
8552       if (AOP_SIZE (result) > 1 &&
8553           !OP_SYMBOL (left)->remat &&
8554           (OP_SYMBOL (left)->liveTo > ic->seq ||
8555            ic->depth))
8556         {
8557           int size = AOP_SIZE (result) - 1;
8558           while (size--)
8559             emitcode ("dec", "%s", rname);
8560         }
8561     }
8562
8563   /* done */
8564   freeAsmop (result, NULL, ic, TRUE);
8565
8566 }
8567
8568 /*-----------------------------------------------------------------*/
8569 /* genPagedPointerGet - emitcode for paged pointer fetch           */
8570 /*-----------------------------------------------------------------*/
8571 static void
8572 genPagedPointerGet (operand * left,
8573                     operand * result,
8574                     iCode * ic)
8575 {
8576   asmop *aop = NULL;
8577   regs *preg = NULL;
8578   char *rname;
8579   sym_link *rtype, *retype, *letype;
8580
8581   rtype = operandType (result);
8582   retype = getSpec (rtype);
8583   letype = getSpec (operandType (left));
8584   aopOp (left, ic, FALSE, FALSE);
8585
8586   /* if the value is already in a pointer register
8587      then don't need anything more */
8588   if (!AOP_INPREG (AOP (left)))
8589     {
8590       /* otherwise get a free pointer register */
8591       aop = newAsmop (0);
8592       preg = getFreePtr (ic, &aop, FALSE);
8593       emitcode ("mov", "%s,%s",
8594                 preg->name,
8595                 aopGet (AOP (left), 0, FALSE, TRUE, FALSE));
8596       rname = preg->name;
8597     }
8598   else
8599     rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE);
8600
8601   freeAsmop (left, NULL, ic, TRUE);
8602   aopOp (result, ic, FALSE, FALSE);
8603
8604   /* if bitfield then unpack the bits */
8605   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8606     genUnpackBits (result, rname, PPOINTER);
8607   else
8608     {
8609       /* we have can just get the values */
8610       int size = AOP_SIZE (result);
8611       int offset = 0;
8612
8613       while (size--)
8614         {
8615
8616           emitcode ("movx", "a,@%s", rname);
8617           aopPut (AOP (result), "a", offset);
8618
8619           offset++;
8620
8621           if (size)
8622             emitcode ("inc", "%s", rname);
8623         }
8624     }
8625
8626   /* now some housekeeping stuff */
8627   if (aop)
8628     {
8629       /* we had to allocate for this iCode */
8630       freeAsmop (NULL, aop, ic, TRUE);
8631     }
8632   else
8633     {
8634       /* we did not allocate which means left
8635          already in a pointer register, then
8636          if size > 0 && this could be used again
8637          we have to point it back to where it
8638          belongs */
8639       if (AOP_SIZE (result) > 1 &&
8640           !OP_SYMBOL (left)->remat &&
8641           (OP_SYMBOL (left)->liveTo > ic->seq ||
8642            ic->depth))
8643         {
8644           int size = AOP_SIZE (result) - 1;
8645           while (size--)
8646             emitcode ("dec", "%s", rname);
8647         }
8648     }
8649
8650   /* done */
8651   freeAsmop (result, NULL, ic, TRUE);
8652
8653
8654 }
8655
8656 /*-----------------------------------------------------------------*/
8657 /* genFarPointerGet - gget value from far space                    */
8658 /*-----------------------------------------------------------------*/
8659 static void
8660 genFarPointerGet (operand * left,
8661                   operand * result, iCode * ic)
8662 {
8663   int size, offset;
8664   sym_link *retype = getSpec (operandType (result));
8665   sym_link *letype = getSpec (operandType (left));
8666   D (emitcode (";", "genFarPointerGet");
8667     );
8668
8669   aopOp (left, ic, FALSE, FALSE);
8670
8671   /* if the operand is already in dptr
8672      then we do nothing else we move the value to dptr */
8673   if (AOP_TYPE (left) != AOP_STR)
8674     {
8675       /* if this is remateriazable */
8676       if (AOP_TYPE (left) == AOP_IMMD)
8677         {
8678           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8679         }
8680       else
8681         {
8682           /* we need to get it byte by byte */
8683           _startLazyDPSEvaluation ();
8684           if (AOP_TYPE (left) != AOP_DPTR)
8685             {
8686               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8687               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8688               if (options.model == MODEL_FLAT24)
8689                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8690             }
8691           else
8692             {
8693               /* We need to generate a load to DPTR indirect through DPTR. */
8694               D (emitcode (";", "genFarPointerGet -- indirection special case.");
8695                 );
8696               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8697               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8698               if (options.model == MODEL_FLAT24)
8699                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8700               emitcode ("pop", "dph");
8701               emitcode ("pop", "dpl");
8702             }
8703           _endLazyDPSEvaluation ();
8704         }
8705     }
8706   /* so dptr know contains the address */
8707   freeAsmop (left, NULL, ic, TRUE);
8708   aopOp (result, ic, FALSE, TRUE);
8709
8710   /* if bit then unpack */
8711   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8712     genUnpackBits (result, "dptr", FPOINTER);
8713   else
8714     {
8715       size = AOP_SIZE (result);
8716       offset = 0;
8717
8718       _startLazyDPSEvaluation ();
8719       while (size--)
8720         {
8721
8722           genSetDPTR (0);
8723           _flushLazyDPS ();
8724
8725           emitcode ("movx", "a,@dptr");
8726           if (size)
8727             emitcode ("inc", "dptr");
8728
8729           aopPut (AOP (result), "a", offset++);
8730         }
8731       _endLazyDPSEvaluation ();
8732     }
8733
8734   freeAsmop (result, NULL, ic, TRUE);
8735 }
8736
8737 /*-----------------------------------------------------------------*/
8738 /* emitcodePointerGet - gget value from code space                  */
8739 /*-----------------------------------------------------------------*/
8740 static void
8741 emitcodePointerGet (operand * left,
8742                     operand * result, iCode * ic)
8743 {
8744   int size, offset;
8745   sym_link *retype = getSpec (operandType (result));
8746
8747   aopOp (left, ic, FALSE, FALSE);
8748
8749   /* if the operand is already in dptr
8750      then we do nothing else we move the value to dptr */
8751   if (AOP_TYPE (left) != AOP_STR)
8752     {
8753       /* if this is remateriazable */
8754       if (AOP_TYPE (left) == AOP_IMMD)
8755         {
8756           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8757         }
8758       else
8759         {                       /* we need to get it byte by byte */
8760           _startLazyDPSEvaluation ();
8761           if (AOP_TYPE (left) != AOP_DPTR)
8762             {
8763               emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
8764               emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
8765               if (options.model == MODEL_FLAT24)
8766                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8767             }
8768           else
8769             {
8770               /* We need to generate a load to DPTR indirect through DPTR. */
8771               D (emitcode (";", "gencodePointerGet -- indirection special case.");
8772                 );
8773               emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE));
8774               emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE));
8775               if (options.model == MODEL_FLAT24)
8776                 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
8777               emitcode ("pop", "dph");
8778               emitcode ("pop", "dpl");
8779             }
8780           _endLazyDPSEvaluation ();
8781         }
8782     }
8783   /* so dptr know contains the address */
8784   freeAsmop (left, NULL, ic, TRUE);
8785   aopOp (result, ic, FALSE, TRUE);
8786
8787   /* if bit then unpack */
8788   if (IS_BITVAR (retype))
8789     genUnpackBits (result, "dptr", CPOINTER);
8790   else
8791     {
8792       size = AOP_SIZE (result);
8793       offset = 0;
8794
8795       _startLazyDPSEvaluation ();
8796       while (size--)
8797         {
8798           genSetDPTR (0);
8799           _flushLazyDPS ();
8800
8801           emitcode ("clr", "a");
8802           emitcode ("movc", "a,@a+dptr");
8803           if (size)
8804             emitcode ("inc", "dptr");
8805           aopPut (AOP (result), "a", offset++);
8806         }
8807       _endLazyDPSEvaluation ();
8808     }
8809
8810   freeAsmop (result, NULL, ic, TRUE);
8811 }
8812
8813 /*-----------------------------------------------------------------*/
8814 /* genGenPointerGet - gget value from generic pointer space        */
8815 /*-----------------------------------------------------------------*/
8816 static void
8817 genGenPointerGet (operand * left,
8818                   operand * result, iCode * ic)
8819 {
8820   int size, offset;
8821   sym_link *retype = getSpec (operandType (result));
8822   sym_link *letype = getSpec (operandType (left));
8823
8824   D (emitcode (";", "genGenPointerGet "); );
8825
8826   aopOp (left, ic, FALSE, TRUE);
8827
8828   /* if the operand is already in dptr
8829      then we do nothing else we move the value to dptr */
8830   if (AOP_TYPE (left) != AOP_STR)
8831     {
8832       /* if this is remateriazable */
8833       if (AOP_TYPE (left) == AOP_IMMD)
8834         {
8835           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE));
8836           emitcode ("mov", "b,#%d", pointerCode (retype));
8837         }
8838       else
8839         {                       /* we need to get it byte by byte */
8840           _startLazyDPSEvaluation ();
8841           if (AOP(left)->type==AOP_DPTR2) {
8842             char *l;
8843             l=aopGet(AOP(left),0,FALSE,FALSE,TRUE);
8844             genSetDPTR(0);
8845             _flushLazyDPS();
8846             emitcode ("mov", "dpl,%s", l);
8847             l=aopGet(AOP(left),1,FALSE,FALSE,TRUE);
8848             genSetDPTR(0);
8849             _flushLazyDPS();
8850             emitcode ("mov", "dph,%s", l);
8851             if (options.model == MODEL_FLAT24) {
8852               l=aopGet(AOP(left),2,FALSE,FALSE,TRUE);
8853               genSetDPTR(0);
8854               _flushLazyDPS();
8855               emitcode ("mov", "dpx,%s", l);
8856               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8857             } else {
8858               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8859             }
8860           } else {
8861             emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE));
8862             emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE));
8863             if (options.model == MODEL_FLAT24) {
8864               emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8865               emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE));
8866             } else {
8867               emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE));
8868             }
8869           }
8870           _endLazyDPSEvaluation ();
8871         }
8872     }
8873   /* so dptr know contains the address */
8874   freeAsmop (left, NULL, ic, TRUE);
8875   aopOp (result, ic, FALSE, TRUE);
8876
8877   /* if bit then unpack */
8878   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8879     genUnpackBits (result, "dptr", GPOINTER);
8880   else
8881     {
8882       size = AOP_SIZE (result);
8883       offset = 0;
8884
8885       while (size--)
8886         {
8887           emitcode ("lcall", "__gptrget");
8888           aopPut (AOP (result), "a", offset++);
8889           if (size)
8890             emitcode ("inc", "dptr");
8891         }
8892     }
8893
8894   freeAsmop (result, NULL, ic, TRUE);
8895 }
8896
8897 /*-----------------------------------------------------------------*/
8898 /* genPointerGet - generate code for pointer get                   */
8899 /*-----------------------------------------------------------------*/
8900 static void
8901 genPointerGet (iCode * ic)
8902 {
8903   operand *left, *result;
8904   sym_link *type, *etype;
8905   int p_type;
8906
8907   D (emitcode (";", "genPointerGet ");
8908     );
8909
8910   left = IC_LEFT (ic);
8911   result = IC_RESULT (ic);
8912
8913   /* depending on the type of pointer we need to
8914      move it to the correct pointer register */
8915   type = operandType (left);
8916   etype = getSpec (type);
8917   /* if left is of type of pointer then it is simple */
8918   if (IS_PTR (type) && !IS_FUNC (type->next))
8919     p_type = DCL_TYPE (type);
8920   else
8921     {
8922       /* we have to go by the storage class */
8923       p_type = PTR_TYPE (SPEC_OCLS (etype));
8924     }
8925
8926   /* now that we have the pointer type we assign
8927      the pointer values */
8928   switch (p_type)
8929     {
8930
8931     case POINTER:
8932     case IPOINTER:
8933       genNearPointerGet (left, result, ic);
8934       break;
8935
8936     case PPOINTER:
8937       genPagedPointerGet (left, result, ic);
8938       break;
8939
8940     case FPOINTER:
8941       genFarPointerGet (left, result, ic);
8942       break;
8943
8944     case CPOINTER:
8945       emitcodePointerGet (left, result, ic);
8946       break;
8947
8948     case GPOINTER:
8949       genGenPointerGet (left, result, ic);
8950       break;
8951     }
8952
8953 }
8954
8955 /*-----------------------------------------------------------------*/
8956 /* genPackBits - generates code for packed bit storage             */
8957 /*-----------------------------------------------------------------*/
8958 static void
8959 genPackBits (sym_link * etype,
8960              operand * right,
8961              char *rname, int p_type)
8962 {
8963   int shCount = 0;
8964   int offset = 0;
8965   int rLen = 0;
8966   int blen, bstr;
8967   char *l;
8968
8969   blen = SPEC_BLEN (etype);
8970   bstr = SPEC_BSTR (etype);
8971
8972   l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
8973   MOVA (l);
8974
8975   /* if the bit lenth is less than or    */
8976   /* it exactly fits a byte then         */
8977   if (SPEC_BLEN (etype) <= 8)
8978     {
8979       shCount = SPEC_BSTR (etype);
8980
8981       /* shift left acc */
8982       AccLsh (shCount);
8983
8984       if (SPEC_BLEN (etype) < 8)
8985         {                       /* if smaller than a byte */
8986
8987
8988           switch (p_type)
8989             {
8990             case POINTER:
8991               emitcode ("mov", "b,a");
8992               emitcode ("mov", "a,@%s", rname);
8993               break;
8994
8995             case FPOINTER:
8996               emitcode ("mov", "b,a");
8997               emitcode ("movx", "a,@dptr");
8998               break;
8999
9000             case GPOINTER:
9001               emitcode ("push", "b");
9002               emitcode ("push", "acc");
9003               emitcode ("lcall", "__gptrget");
9004               emitcode ("pop", "b");
9005               break;
9006             }
9007
9008           emitcode ("anl", "a,#0x%02x", (unsigned char)
9009                     ((unsigned char) (0xFF << (blen + bstr)) |
9010                      (unsigned char) (0xFF >> (8 - bstr))));
9011           emitcode ("orl", "a,b");
9012           if (p_type == GPOINTER)
9013             emitcode ("pop", "b");
9014         }
9015     }
9016
9017   switch (p_type)
9018     {
9019     case POINTER:
9020       emitcode ("mov", "@%s,a", rname);
9021       break;
9022
9023     case FPOINTER:
9024       emitcode ("movx", "@dptr,a");
9025       break;
9026
9027     case GPOINTER:
9028       emitcode ("lcall", "__gptrput");
9029       break;
9030     }
9031
9032   /* if we r done */
9033   if (SPEC_BLEN (etype) <= 8)
9034     return;
9035
9036   emitcode ("inc", "%s", rname);
9037   rLen = SPEC_BLEN (etype);
9038
9039   /* now generate for lengths greater than one byte */
9040   while (1)
9041     {
9042
9043       l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE);
9044
9045       rLen -= 8;
9046       if (rLen < 8)
9047         break;
9048
9049       switch (p_type)
9050         {
9051         case POINTER:
9052           if (*l == '@')
9053             {
9054               MOVA (l);
9055               emitcode ("mov", "@%s,a", rname);
9056             }
9057           else
9058             emitcode ("mov", "@%s,%s", rname, l);
9059           break;
9060
9061         case FPOINTER:
9062           MOVA (l);
9063           emitcode ("movx", "@dptr,a");
9064           break;
9065
9066         case GPOINTER:
9067           MOVA (l);
9068           emitcode ("lcall", "__gptrput");
9069           break;
9070         }
9071       emitcode ("inc", "%s", rname);
9072     }
9073
9074   MOVA (l);
9075
9076   /* last last was not complete */
9077   if (rLen)
9078     {
9079       /* save the byte & read byte */
9080       switch (p_type)
9081         {
9082         case POINTER:
9083           emitcode ("mov", "b,a");
9084           emitcode ("mov", "a,@%s", rname);
9085           break;
9086
9087         case FPOINTER:
9088           emitcode ("mov", "b,a");
9089           emitcode ("movx", "a,@dptr");
9090           break;
9091
9092         case GPOINTER:
9093           emitcode ("push", "b");
9094           emitcode ("push", "acc");
9095           emitcode ("lcall", "__gptrget");
9096           emitcode ("pop", "b");
9097           break;
9098         }
9099
9100       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1 << rLen));
9101       emitcode ("orl", "a,b");
9102     }
9103
9104   if (p_type == GPOINTER)
9105     emitcode ("pop", "b");
9106
9107   switch (p_type)
9108     {
9109
9110     case POINTER:
9111       emitcode ("mov", "@%s,a", rname);
9112       break;
9113
9114     case FPOINTER:
9115       emitcode ("movx", "@dptr,a");
9116       break;
9117
9118     case GPOINTER:
9119       emitcode ("lcall", "__gptrput");
9120       break;
9121     }
9122 }
9123 /*-----------------------------------------------------------------*/
9124 /* genDataPointerSet - remat pointer to data space                 */
9125 /*-----------------------------------------------------------------*/
9126 static void
9127 genDataPointerSet (operand * right,
9128                    operand * result,
9129                    iCode * ic)
9130 {
9131   int size, offset = 0;
9132   char *l, buffer[256];
9133
9134   aopOp (right, ic, FALSE, FALSE);
9135
9136   l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE);
9137   size = AOP_SIZE (right);
9138   while (size--)
9139     {
9140       if (offset)
9141         sprintf (buffer, "(%s + %d)", l + 1, offset);
9142       else
9143         sprintf (buffer, "%s", l + 1);
9144       emitcode ("mov", "%s,%s", buffer,
9145                 aopGet (AOP (right), offset++, FALSE, FALSE, FALSE));
9146     }
9147
9148   freeAsmop (right, NULL, ic, TRUE);
9149   freeAsmop (result, NULL, ic, TRUE);
9150 }
9151
9152 /*-----------------------------------------------------------------*/
9153 /* genNearPointerSet - emitcode for near pointer put                */
9154 /*-----------------------------------------------------------------*/
9155 static void
9156 genNearPointerSet (operand * right,
9157                    operand * result,
9158                    iCode * ic)
9159 {
9160   asmop *aop = NULL;
9161   regs *preg = NULL;
9162   char *rname, *l;
9163   sym_link *retype, *letype;
9164   sym_link *ptype = operandType (result);
9165
9166   retype = getSpec (operandType (right));
9167   letype = getSpec (ptype);
9168
9169   aopOp (result, ic, FALSE, FALSE);
9170
9171   /* if the result is rematerializable &
9172      in data space & not a bit variable */
9173   if (AOP_TYPE (result) == AOP_IMMD &&
9174       DCL_TYPE (ptype) == POINTER &&
9175       !IS_BITVAR (retype) &&
9176       !IS_BITVAR (letype))
9177     {
9178       genDataPointerSet (right, result, ic);
9179       return;
9180     }
9181
9182   /* if the value is already in a pointer register
9183      then don't need anything more */
9184   if (!AOP_INPREG (AOP (result)))
9185     {
9186       /* otherwise get a free pointer register */
9187       aop = newAsmop (0);
9188       preg = getFreePtr (ic, &aop, FALSE);
9189       emitcode ("mov", "%s,%s",
9190                 preg->name,
9191                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9192       rname = preg->name;
9193     }
9194   else
9195     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9196
9197   freeAsmop (result, NULL, ic, TRUE);
9198   aopOp (right, ic, FALSE, FALSE);
9199
9200   /* if bitfield then unpack the bits */
9201   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9202     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
9203   else
9204     {
9205       /* we have can just get the values */
9206       int size = AOP_SIZE (right);
9207       int offset = 0;
9208
9209       while (size--)
9210         {
9211           l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE);
9212           if (*l == '@')
9213             {
9214               MOVA (l);
9215               emitcode ("mov", "@%s,a", rname);
9216             }
9217           else
9218             emitcode ("mov", "@%s,%s", rname, l);
9219           if (size)
9220             emitcode ("inc", "%s", rname);
9221           offset++;
9222         }
9223     }
9224
9225   /* now some housekeeping stuff */
9226   if (aop)
9227     {
9228       /* we had to allocate for this iCode */
9229       freeAsmop (NULL, aop, ic, TRUE);
9230     }
9231   else
9232     {
9233       /* we did not allocate which means left
9234          already in a pointer register, then
9235          if size > 0 && this could be used again
9236          we have to point it back to where it
9237          belongs */
9238       if (AOP_SIZE (right) > 1 &&
9239           !OP_SYMBOL (result)->remat &&
9240           (OP_SYMBOL (result)->liveTo > ic->seq ||
9241            ic->depth))
9242         {
9243           int size = AOP_SIZE (right) - 1;
9244           while (size--)
9245             emitcode ("dec", "%s", rname);
9246         }
9247     }
9248
9249   /* done */
9250   freeAsmop (right, NULL, ic, TRUE);
9251
9252
9253 }
9254
9255 /*-----------------------------------------------------------------*/
9256 /* genPagedPointerSet - emitcode for Paged pointer put             */
9257 /*-----------------------------------------------------------------*/
9258 static void
9259 genPagedPointerSet (operand * right,
9260                     operand * result,
9261                     iCode * ic)
9262 {
9263   asmop *aop = NULL;
9264   regs *preg = NULL;
9265   char *rname, *l;
9266   sym_link *retype, *letype;
9267
9268   retype = getSpec (operandType (right));
9269   letype = getSpec (operandType (result));
9270
9271   aopOp (result, ic, FALSE, FALSE);
9272
9273   /* if the value is already in a pointer register
9274      then don't need anything more */
9275   if (!AOP_INPREG (AOP (result)))
9276     {
9277       /* otherwise get a free pointer register */
9278       aop = newAsmop (0);
9279       preg = getFreePtr (ic, &aop, FALSE);
9280       emitcode ("mov", "%s,%s",
9281                 preg->name,
9282                 aopGet (AOP (result), 0, FALSE, TRUE, FALSE));
9283       rname = preg->name;
9284     }
9285   else
9286     rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE);
9287
9288   freeAsmop (result, NULL, ic, TRUE);
9289   aopOp (right, ic, FALSE, FALSE);
9290
9291   /* if bitfield then unpack the bits */
9292   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9293     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
9294   else
9295     {
9296       /* we have can just get the values */
9297       int size = AOP_SIZE (right);
9298       int offset = 0;
9299
9300       while (size--)
9301         {
9302           l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE);
9303
9304           MOVA (l);
9305           emitcode ("movx", "@%s,a", rname);
9306
9307           if (size)
9308             emitcode ("inc", "%s", rname);
9309
9310           offset++;
9311         }
9312     }
9313
9314   /* now some housekeeping stuff */
9315   if (aop)
9316     {
9317       /* we had to allocate for this iCode */
9318       freeAsmop (NULL, aop, ic, TRUE);
9319     }
9320   else
9321     {
9322       /* we did not allocate which means left
9323          already in a pointer register, then
9324          if size > 0 && this could be used again
9325          we have to point it back to where it
9326          belongs */
9327       if (AOP_SIZE (right) > 1 &&
9328           !OP_SYMBOL (result)->remat &&
9329           (OP_SYMBOL (result)->liveTo > ic->seq ||
9330            ic->depth))
9331         {
9332           int size = AOP_SIZE (right) - 1;
9333           while (size--)
9334             emitcode ("dec", "%s", rname);
9335         }
9336     }
9337
9338   /* done */
9339   freeAsmop (right, NULL, ic, TRUE);
9340
9341
9342 }
9343
9344 /*-----------------------------------------------------------------*/
9345 /* genFarPointerSet - set value from far space                     */
9346 /*-----------------------------------------------------------------*/
9347 static void
9348 genFarPointerSet (operand * right,
9349                   operand * result, iCode * ic)
9350 {
9351   int size, offset;
9352   sym_link *retype = getSpec (operandType (right));
9353   sym_link *letype = getSpec (operandType (result));
9354
9355   aopOp (result, ic, FALSE, FALSE);
9356
9357   /* if the operand is already in dptr
9358      then we do nothing else we move the value to dptr */
9359   if (AOP_TYPE (result) != AOP_STR)
9360     {
9361       /* if this is remateriazable */
9362       if (AOP_TYPE (result) == AOP_IMMD)
9363         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9364       else
9365         {
9366           /* we need to get it byte by byte */
9367           _startLazyDPSEvaluation ();
9368           if (AOP_TYPE (result) != AOP_DPTR)
9369             {
9370               emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9371               emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9372               if (options.model == MODEL_FLAT24)
9373                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9374             }
9375           else
9376             {
9377               /* We need to generate a load to DPTR indirect through DPTR. */
9378               D (emitcode (";", "genFarPointerSet -- indirection special case.");
9379                 );
9380               emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE));
9381               emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE));
9382               if (options.model == MODEL_FLAT24)
9383                 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9384               emitcode ("pop", "dph");
9385               emitcode ("pop", "dpl");
9386             }
9387           _endLazyDPSEvaluation ();
9388         }
9389     }
9390   /* so dptr know contains the address */
9391   freeAsmop (result, NULL, ic, TRUE);
9392   aopOp (right, ic, FALSE, TRUE);
9393
9394   /* if bit then unpack */
9395   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9396     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
9397   else
9398     {
9399       size = AOP_SIZE (right);
9400       offset = 0;
9401
9402       _startLazyDPSEvaluation ();
9403       while (size--)
9404         {
9405           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9406           MOVA (l);
9407
9408           genSetDPTR (0);
9409           _flushLazyDPS ();
9410
9411           emitcode ("movx", "@dptr,a");
9412           if (size)
9413             emitcode ("inc", "dptr");
9414         }
9415       _endLazyDPSEvaluation ();
9416     }
9417
9418   freeAsmop (right, NULL, ic, TRUE);
9419 }
9420
9421 /*-----------------------------------------------------------------*/
9422 /* genGenPointerSet - set value from generic pointer space         */
9423 /*-----------------------------------------------------------------*/
9424 static void
9425 genGenPointerSet (operand * right,
9426                   operand * result, iCode * ic)
9427 {
9428   int size, offset;
9429   sym_link *retype = getSpec (operandType (right));
9430   sym_link *letype = getSpec (operandType (result));
9431
9432   aopOp (result, ic, FALSE, TRUE);
9433
9434   /* if the operand is already in dptr
9435      then we do nothing else we move the value to dptr */
9436   if (AOP_TYPE (result) != AOP_STR)
9437     {
9438       _startLazyDPSEvaluation ();
9439       /* if this is remateriazable */
9440       if (AOP_TYPE (result) == AOP_IMMD)
9441         {
9442           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9443           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE));
9444         }
9445       else
9446         {                       /* we need to get it byte by byte */
9447           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE));
9448           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE));
9449           if (options.model == MODEL_FLAT24) {
9450             emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9451             emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE));
9452           } else {
9453             emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE));
9454           }
9455         }
9456       _endLazyDPSEvaluation ();
9457     }
9458   /* so dptr know contains the address */
9459   freeAsmop (result, NULL, ic, TRUE);
9460   aopOp (right, ic, FALSE, TRUE);
9461
9462   /* if bit then unpack */
9463   if (IS_BITVAR (retype) || IS_BITVAR (letype))
9464     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
9465   else
9466     {
9467       size = AOP_SIZE (right);
9468       offset = 0;
9469
9470       _startLazyDPSEvaluation ();
9471       while (size--)
9472         {
9473           char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE);
9474           MOVA (l);
9475
9476           genSetDPTR (0);
9477           _flushLazyDPS ();
9478
9479           emitcode ("lcall", "__gptrput");
9480           if (size)
9481             emitcode ("inc", "dptr");
9482         }
9483       _endLazyDPSEvaluation ();
9484     }
9485
9486   freeAsmop (right, NULL, ic, TRUE);
9487 }
9488
9489 /*-----------------------------------------------------------------*/
9490 /* genPointerSet - stores the value into a pointer location        */
9491 /*-----------------------------------------------------------------*/
9492 static void
9493 genPointerSet (iCode * ic)
9494 {
9495   operand *right, *result;
9496   sym_link *type, *etype;
9497   int p_type;
9498
9499   D (emitcode (";", "genPointerSet ");
9500     );
9501
9502   right = IC_RIGHT (ic);
9503   result = IC_RESULT (ic);
9504
9505   /* depending on the type of pointer we need to
9506      move it to the correct pointer register */
9507   type = operandType (result);
9508   etype = getSpec (type);
9509   /* if left is of type of pointer then it is simple */
9510   if (IS_PTR (type) && !IS_FUNC (type->next))
9511     {
9512       p_type = DCL_TYPE (type);
9513     }
9514   else
9515     {
9516       /* we have to go by the storage class */
9517       p_type = PTR_TYPE (SPEC_OCLS (etype));
9518     }
9519
9520   /* now that we have the pointer type we assign
9521      the pointer values */
9522   switch (p_type)
9523     {
9524
9525     case POINTER:
9526     case IPOINTER:
9527       genNearPointerSet (right, result, ic);
9528       break;
9529
9530     case PPOINTER:
9531       genPagedPointerSet (right, result, ic);
9532       break;
9533
9534     case FPOINTER:
9535       genFarPointerSet (right, result, ic);
9536       break;
9537
9538     case GPOINTER:
9539       genGenPointerSet (right, result, ic);
9540       break;
9541     }
9542
9543 }
9544
9545 /*-----------------------------------------------------------------*/
9546 /* genIfx - generate code for Ifx statement                        */
9547 /*-----------------------------------------------------------------*/
9548 static void
9549 genIfx (iCode * ic, iCode * popIc)
9550 {
9551   operand *cond = IC_COND (ic);
9552   int isbit = 0;
9553
9554   D (emitcode (";", "genIfx "););
9555
9556   aopOp (cond, ic, FALSE, FALSE);
9557
9558   /* get the value into acc */
9559   if (AOP_TYPE (cond) != AOP_CRY)
9560     toBoolean (cond);
9561   else
9562     isbit = 1;
9563   /* the result is now in the accumulator */
9564   freeAsmop (cond, NULL, ic, TRUE);
9565
9566   /* if there was something to be popped then do it */
9567   if (popIc)
9568     genIpop (popIc);
9569
9570   /* if the condition is  a bit variable */
9571   if (isbit && IS_ITEMP (cond) &&
9572       SPIL_LOC (cond))
9573     genIfxJump (ic, SPIL_LOC (cond)->rname);
9574   else if (isbit && !IS_ITEMP (cond))
9575     genIfxJump (ic, OP_SYMBOL (cond)->rname);
9576   else
9577     genIfxJump (ic, "a");
9578
9579   ic->generated = 1;
9580 }
9581
9582 /*-----------------------------------------------------------------*/
9583 /* genAddrOf - generates code for address of                       */
9584 /*-----------------------------------------------------------------*/
9585 static void
9586 genAddrOf (iCode * ic)
9587 {
9588   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9589   int size, offset;
9590
9591   D (emitcode (";", "genAddrOf ");
9592     );
9593
9594   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
9595
9596   /* if the operand is on the stack then we
9597      need to get the stack offset of this
9598      variable */
9599   if (sym->onStack)
9600     {
9601       /* if it has an offset then we need to compute
9602          it */
9603       if (sym->stack)
9604         {
9605           emitcode ("mov", "a,_bp");
9606           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
9607           aopPut (AOP (IC_RESULT (ic)), "a", 0);
9608         }
9609       else
9610         {
9611           /* we can just move _bp */
9612           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
9613         }
9614       /* fill the result with zero */
9615       size = AOP_SIZE (IC_RESULT (ic)) - 1;
9616
9617
9618       if (options.stack10bit && size < (FPTRSIZE - 1))
9619         {
9620           fprintf (stderr,
9621                    "*** warning: pointer to stack var truncated.\n");
9622         }
9623
9624       offset = 1;
9625       while (size--)
9626         {
9627           /* Yuck! */
9628           if (options.stack10bit && offset == 2)
9629             {
9630               aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
9631             }
9632           else
9633             {
9634               aopPut (AOP (IC_RESULT (ic)), zero, offset++);
9635             }
9636         }
9637
9638       goto release;
9639     }
9640
9641   /* object not on stack then we need the name */
9642   size = AOP_SIZE (IC_RESULT (ic));
9643   offset = 0;
9644
9645   while (size--)
9646     {
9647       char s[SDCC_NAME_MAX];
9648       if (offset)
9649         sprintf (s, "#(%s >> %d)",
9650                  sym->rname,
9651                  offset * 8);
9652       else
9653         sprintf (s, "#%s", sym->rname);
9654       aopPut (AOP (IC_RESULT (ic)), s, offset++);
9655     }
9656
9657 release:
9658   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9659
9660 }
9661
9662 /*-----------------------------------------------------------------*/
9663 /* genArrayInit - generates code for address of                       */
9664 /*-----------------------------------------------------------------*/
9665 static void
9666 genArrayInit (iCode * ic)
9667 {
9668     literalList *iLoop;
9669     int         ix, count;
9670     int         elementSize = 0, eIndex;
9671     unsigned    val, lastVal;
9672     sym_link    *type;
9673     operand     *left=IC_LEFT(ic);
9674     
9675     D (emitcode (";", "genArrayInit "););
9676
9677     aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
9678     
9679     if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
9680     {
9681         // Load immediate value into DPTR.
9682         emitcode("mov", "dptr, %s",
9683              aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE));
9684     }
9685     else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
9686     {
9687 #if 0
9688       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9689               "Unexpected operand to genArrayInit.\n");
9690       exit(1);
9691 #else
9692       // a regression because of SDCCcse.c:1.52
9693       emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
9694       emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE));
9695       if (options.model == MODEL_FLAT24)
9696         emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE));
9697 #endif
9698     }
9699     
9700     type = operandType(IC_LEFT(ic));
9701     
9702     if (type && type->next)
9703     {
9704         elementSize = getSize(type->next);
9705     }
9706     else
9707     {
9708         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9709                                 "can't determine element size in genArrayInit.\n");
9710         exit(1);
9711     }
9712     
9713     iLoop = IC_ARRAYILIST(ic);
9714     lastVal = 0xffff;
9715     
9716     while (iLoop)
9717     {
9718         bool firstpass = TRUE;
9719         
9720         emitcode(";", "store %d x 0x%x to DPTR (element size %d)", 
9721                  iLoop->count, (int)iLoop->literalValue, elementSize);
9722         
9723         ix = iLoop->count;
9724         
9725         while (ix)
9726         {
9727             symbol *tlbl = NULL;
9728             
9729             count = ix > 256 ? 256 : ix;
9730             
9731             if (count > 1)
9732             {
9733                 tlbl = newiTempLabel (NULL);
9734                 if (firstpass || (count & 0xff))
9735                 {
9736                     emitcode("mov", "b, #0x%x", count & 0xff);
9737                 }
9738                 
9739                 emitcode ("", "%05d$:", tlbl->key + 100);
9740             }
9741             
9742             firstpass = FALSE;
9743                 
9744             for (eIndex = 0; eIndex < elementSize; eIndex++)
9745             {
9746                 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
9747                 if (val != lastVal)
9748                 {
9749                     emitcode("mov", "a, #0x%x", val);
9750                     lastVal = val;
9751                 }
9752                 
9753                 emitcode("movx", "@dptr, a");
9754                 emitcode("inc", "dptr");
9755             }
9756             
9757             if (count > 1)
9758             {
9759                 emitcode("djnz", "b, %05d$", tlbl->key + 100);
9760             }
9761             
9762             ix -= count;
9763         }
9764         
9765         iLoop = iLoop->next;
9766     }
9767     
9768     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
9769 }
9770
9771 /*-----------------------------------------------------------------*/
9772 /* genFarFarAssign - assignment when both are in far space         */
9773 /*-----------------------------------------------------------------*/
9774 static void
9775 genFarFarAssign (operand * result, operand * right, iCode * ic)
9776 {
9777   int size = AOP_SIZE (right);
9778   int offset = 0;
9779   symbol *rSym = NULL;
9780
9781   if (size == 1)
9782   {
9783       /* quick & easy case. */
9784       D(emitcode(";","genFarFarAssign (1 byte case)"););      
9785       MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE));
9786       freeAsmop (right, NULL, ic, FALSE);
9787       /* now assign DPTR to result */
9788       _G.accInUse++;
9789       aopOp(result, ic, FALSE, FALSE);
9790       _G.accInUse--;
9791       aopPut(AOP(result), "a", 0);
9792       freeAsmop(result, NULL, ic, FALSE);
9793       return;
9794   }
9795   
9796   /* See if we've got an underlying symbol to abuse. */
9797   if (IS_SYMOP(result) && OP_SYMBOL(result))
9798   {
9799       if (IS_TRUE_SYMOP(result))
9800       {
9801           rSym = OP_SYMBOL(result);
9802       }
9803       else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
9804       {
9805           rSym = OP_SYMBOL(result)->usl.spillLoc;
9806       }
9807   }
9808              
9809   if (size > 1 && rSym && rSym->rname && !rSym->onStack)
9810   {
9811       /* We can use the '390 auto-toggle feature to good effect here. */
9812       
9813       D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
9814       emitcode("mov", "dps, #0x21");    /* Select DPTR2 & auto-toggle. */
9815       emitcode ("mov", "dptr,#%s", rSym->rname); 
9816       /* DP2 = result, DP1 = right, DP1 is current. */
9817       while (size)
9818       {
9819           emitcode("movx", "a,@dptr");
9820           emitcode("movx", "@dptr,a");
9821           if (--size)
9822           {
9823                emitcode("inc", "dptr");
9824                emitcode("inc", "dptr");
9825           }
9826       }
9827       emitcode("mov", "dps, #0");
9828       freeAsmop (right, NULL, ic, FALSE);
9829 #if 0
9830 some alternative code for processors without auto-toggle
9831 no time to test now, so later well put in...kpb
9832         D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
9833         emitcode("mov", "dps, #0x01");  /* Select DPTR2. */
9834         emitcode ("mov", "dptr,#%s", rSym->rname); 
9835         /* DP2 = result, DP1 = right, DP1 is current. */
9836         while (size)
9837         {
9838           --size;
9839           emitcode("movx", "a,@dptr");
9840           if (size)
9841             emitcode("inc", "dptr");
9842           emitcode("inc", "dps");
9843           emitcode("movx", "@dptr,a");
9844           if (size)
9845             emitcode("inc", "dptr");
9846           emitcode("inc", "dps");
9847         }
9848         emitcode("mov", "dps, #0");
9849         freeAsmop (right, NULL, ic, FALSE);
9850 #endif
9851   }
9852   else
9853   {
9854       D (emitcode (";", "genFarFarAssign"););
9855       aopOp (result, ic, TRUE, TRUE);
9856
9857       _startLazyDPSEvaluation ();
9858       
9859       while (size--)
9860         {
9861           aopPut (AOP (result),
9862                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset);
9863           offset++;
9864         }
9865       _endLazyDPSEvaluation ();
9866       freeAsmop (result, NULL, ic, FALSE);
9867       freeAsmop (right, NULL, ic, FALSE);
9868   }
9869 }
9870
9871 /*-----------------------------------------------------------------*/
9872 /* genAssign - generate code for assignment                        */
9873 /*-----------------------------------------------------------------*/
9874 static void
9875 genAssign (iCode * ic)
9876 {
9877   operand *result, *right;
9878   int size, offset;
9879   unsigned long lit = 0L;
9880
9881   D (emitcode (";", "genAssign ");
9882     );
9883
9884   result = IC_RESULT (ic);
9885   right = IC_RIGHT (ic);
9886
9887   /* if they are the same */
9888   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9889     return;
9890
9891   aopOp (right, ic, FALSE, FALSE);
9892
9893   emitcode (";", "genAssign: resultIsFar = %s",
9894             isOperandInFarSpace (result) ?
9895             "TRUE" : "FALSE");
9896
9897   /* special case both in far space */
9898   if ((AOP_TYPE (right) == AOP_DPTR ||
9899        AOP_TYPE (right) == AOP_DPTR2) &&
9900   /* IS_TRUE_SYMOP(result)       && */
9901       isOperandInFarSpace (result))
9902     {
9903       genFarFarAssign (result, right, ic);
9904       return;
9905     }
9906
9907   aopOp (result, ic, TRUE, FALSE);
9908
9909   /* if they are the same registers */
9910   if (sameRegs (AOP (right), AOP (result)))
9911     goto release;
9912
9913   /* if the result is a bit */
9914   if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
9915     {
9916       /* if the right size is a literal then
9917          we know what the value is */
9918       if (AOP_TYPE (right) == AOP_LIT)
9919         {
9920           if (((int) operandLitValue (right)))
9921             aopPut (AOP (result), one, 0);
9922           else
9923             aopPut (AOP (result), zero, 0);
9924           goto release;
9925         }
9926
9927       /* the right is also a bit variable */
9928       if (AOP_TYPE (right) == AOP_CRY)
9929         {
9930           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9931           aopPut (AOP (result), "c", 0);
9932           goto release;
9933         }
9934
9935       /* we need to or */
9936       toBoolean (right);
9937       aopPut (AOP (result), "a", 0);
9938       goto release;
9939     }
9940
9941   /* bit variables done */
9942   /* general case */
9943   size = AOP_SIZE (result);
9944   offset = 0;
9945   if (AOP_TYPE (right) == AOP_LIT)
9946     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9947
9948   if ((size > 1) &&
9949       (AOP_TYPE (result) != AOP_REG) &&
9950       (AOP_TYPE (right) == AOP_LIT) &&
9951       !IS_FLOAT (operandType (right)))
9952     {
9953       _startLazyDPSEvaluation ();
9954       while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
9955         {
9956           aopPut (AOP (result),
9957                   aopGet (AOP (right), offset, FALSE, FALSE, TRUE),
9958                   offset);
9959           offset++;
9960           size--;
9961         }
9962       /* And now fill the rest with zeros. */
9963       if (size)
9964         {
9965           emitcode ("clr", "a");
9966         }
9967       while (size--)
9968         {
9969           aopPut (AOP (result), "a", offset++);
9970         }
9971       _endLazyDPSEvaluation ();
9972     }
9973   else
9974     {
9975       _startLazyDPSEvaluation ();
9976       while (size--)
9977         {
9978           aopPut (AOP (result),
9979                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
9980                   offset);
9981           offset++;
9982         }
9983       _endLazyDPSEvaluation ();
9984     }
9985
9986 release:
9987   freeAsmop (right, NULL, ic, FALSE);
9988   freeAsmop (result, NULL, ic, TRUE);
9989 }
9990
9991 /*-----------------------------------------------------------------*/
9992 /* genJumpTab - generates code for jump table                      */
9993 /*-----------------------------------------------------------------*/
9994 static void
9995 genJumpTab (iCode * ic)
9996 {
9997   symbol *jtab;
9998   char *l;
9999
10000   D (emitcode (";", "genJumpTab ");
10001     );
10002
10003   aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10004   /* get the condition into accumulator */
10005   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE);
10006   MOVA (l);
10007   /* multiply by four! */
10008   emitcode ("add", "a,acc");
10009   emitcode ("add", "a,acc");
10010   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10011
10012   jtab = newiTempLabel (NULL);
10013   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10014   emitcode ("jmp", "@a+dptr");
10015   emitcode ("", "%05d$:", jtab->key + 100);
10016   /* now generate the jump labels */
10017   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10018        jtab = setNextItem (IC_JTLABELS (ic)))
10019     emitcode ("ljmp", "%05d$", jtab->key + 100);
10020
10021 }
10022
10023 /*-----------------------------------------------------------------*/
10024 /* genCast - gen code for casting                                  */
10025 /*-----------------------------------------------------------------*/
10026 static void
10027 genCast (iCode * ic)
10028 {
10029   operand *result = IC_RESULT (ic);
10030   sym_link *ctype = operandType (IC_LEFT (ic));
10031   sym_link *rtype = operandType (IC_RIGHT (ic));
10032   operand *right = IC_RIGHT (ic);
10033   int size, offset;
10034
10035   D (emitcode (";", "genCast ");
10036     );
10037
10038   /* if they are equivalent then do nothing */
10039   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10040     return;
10041
10042   aopOp (right, ic, FALSE, FALSE);
10043   aopOp (result, ic, FALSE, AOP_TYPE (right) == AOP_DPTR);
10044
10045   /* if the result is a bit */
10046   // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10047   if (IS_BITVAR(OP_SYMBOL(result)->type))
10048     {
10049       /* if the right size is a literal then
10050          we know what the value is */
10051       if (AOP_TYPE (right) == AOP_LIT)
10052         {
10053           if (((int) operandLitValue (right)))
10054             aopPut (AOP (result), one, 0);
10055           else
10056             aopPut (AOP (result), zero, 0);
10057
10058           goto release;
10059         }
10060
10061       /* the right is also a bit variable */
10062       if (AOP_TYPE (right) == AOP_CRY)
10063         {
10064           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10065           aopPut (AOP (result), "c", 0);
10066           goto release;
10067         }
10068
10069       /* we need to or */
10070       toBoolean (right);
10071       aopPut (AOP (result), "a", 0);
10072       goto release;
10073     }
10074
10075   /* if they are the same size : or less */
10076   if (AOP_SIZE (result) <= AOP_SIZE (right))
10077     {
10078
10079       /* if they are in the same place */
10080       if (sameRegs (AOP (right), AOP (result)))
10081         goto release;
10082
10083       /* if they in different places then copy */
10084       size = AOP_SIZE (result);
10085       offset = 0;
10086       _startLazyDPSEvaluation ();
10087       while (size--)
10088         {
10089           aopPut (AOP (result),
10090                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10091                   offset);
10092           offset++;
10093         }
10094       _endLazyDPSEvaluation ();
10095       goto release;
10096     }
10097
10098
10099   /* if the result is of type pointer */
10100   if (IS_PTR (ctype))
10101     {
10102
10103       int p_type;
10104       sym_link *type = operandType (right);
10105
10106       /* pointer to generic pointer */
10107       if (IS_GENPTR (ctype))
10108         {
10109           char *l = zero;
10110
10111           if (IS_PTR (type))
10112             {
10113               p_type = DCL_TYPE (type);
10114             }
10115           else
10116             {
10117 #if OLD_CAST_BEHAVIOR
10118               /* KV: we are converting a non-pointer type to
10119                * a generic pointer. This (ifdef'd out) code
10120                * says that the resulting generic pointer
10121                * should have the same class as the storage
10122                * location of the non-pointer variable.
10123                *
10124                * For example, converting an int (which happens
10125                * to be stored in DATA space) to a pointer results
10126                * in a DATA generic pointer; if the original int
10127                * in XDATA space, so will be the resulting pointer.
10128                *
10129                * I don't like that behavior, and thus this change:
10130                * all such conversions will be forced to XDATA and
10131                * throw a warning. If you want some non-XDATA
10132                * type, or you want to suppress the warning, you
10133                * must go through an intermediate cast, like so:
10134                *
10135                * char _generic *gp = (char _xdata *)(intVar);
10136                */
10137               sym_link *etype = getSpec (type);
10138
10139               /* we have to go by the storage class */
10140               if (SPEC_OCLS (etype) != generic)
10141                 {
10142                   p_type = PTR_TYPE (SPEC_OCLS (etype));
10143                 }
10144               else
10145 #endif
10146                 {
10147                   /* Converting unknown class (i.e. register variable)
10148                    * to generic pointer. This is not good, but
10149                    * we'll make a guess (and throw a warning).
10150                    */
10151                   p_type = FPOINTER;
10152                   werror (W_INT_TO_GEN_PTR_CAST);
10153                 }
10154             }
10155
10156           /* the first two bytes are known */
10157           size = GPTRSIZE - 1;
10158           offset = 0;
10159           _startLazyDPSEvaluation ();
10160           while (size--)
10161             {
10162               aopPut (AOP (result),
10163                       aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10164                       offset);
10165               offset++;
10166             }
10167           _endLazyDPSEvaluation ();
10168
10169           /* the last byte depending on type */
10170           switch (p_type)
10171             {
10172             case IPOINTER:
10173             case POINTER:
10174               l = zero;
10175               break;
10176             case FPOINTER:
10177               l = one;
10178               break;
10179             case CPOINTER:
10180               l = "#0x02";
10181               break;
10182             case PPOINTER:
10183               l = "#0x03";
10184               break;
10185
10186             default:
10187               /* this should never happen */
10188               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10189                       "got unknown pointer type");
10190               exit (1);
10191             }
10192           aopPut (AOP (result), l, GPTRSIZE - 1);
10193           goto release;
10194         }
10195
10196       /* just copy the pointers */
10197       size = AOP_SIZE (result);
10198       offset = 0;
10199       _startLazyDPSEvaluation ();
10200       while (size--)
10201         {
10202           aopPut (AOP (result),
10203                   aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10204                   offset);
10205           offset++;
10206         }
10207       _endLazyDPSEvaluation ();
10208       goto release;
10209     }
10210
10211   /* so we now know that the size of destination is greater
10212      than the size of the source */
10213   /* we move to result for the size of source */
10214   size = AOP_SIZE (right);
10215   offset = 0;
10216   _startLazyDPSEvaluation ();
10217   while (size--)
10218     {
10219       aopPut (AOP (result),
10220               aopGet (AOP (right), offset, FALSE, FALSE, FALSE),
10221               offset);
10222       offset++;
10223     }
10224   _endLazyDPSEvaluation ();
10225
10226   /* now depending on the sign of the source && destination */
10227   size = AOP_SIZE (result) - AOP_SIZE (right);
10228   /* if unsigned or not an integral type */
10229   /* also, if the source is a bit, we don't need to sign extend, because
10230    * it can't possibly have set the sign bit.
10231    */
10232   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
10233     {
10234       while (size--)
10235         {
10236           aopPut (AOP (result), zero, offset++);
10237         }
10238     }
10239   else
10240     {
10241       /* we need to extend the sign :{ */
10242       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10243                         FALSE, FALSE, TRUE);
10244       MOVA (l);
10245       emitcode ("rlc", "a");
10246       emitcode ("subb", "a,acc");
10247       while (size--)
10248         aopPut (AOP (result), "a", offset++);
10249     }
10250
10251   /* we are done hurray !!!! */
10252
10253 release:
10254   freeAsmop (right, NULL, ic, TRUE);
10255   freeAsmop (result, NULL, ic, TRUE);
10256
10257 }
10258
10259 /*-----------------------------------------------------------------*/
10260 /* genDjnz - generate decrement & jump if not zero instrucion      */
10261 /*-----------------------------------------------------------------*/
10262 static int
10263 genDjnz (iCode * ic, iCode * ifx)
10264 {
10265   symbol *lbl, *lbl1;
10266   if (!ifx)
10267     return 0;
10268
10269   /* if the if condition has a false label
10270      then we cannot save */
10271   if (IC_FALSE (ifx))
10272     return 0;
10273
10274   /* if the minus is not of the form
10275      a = a - 1 */
10276   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10277       !IS_OP_LITERAL (IC_RIGHT (ic)))
10278     return 0;
10279
10280   if (operandLitValue (IC_RIGHT (ic)) != 1)
10281     return 0;
10282
10283   /* if the size of this greater than one then no
10284      saving */
10285   if (getSize (operandType (IC_RESULT (ic))) > 1)
10286     return 0;
10287
10288   /* otherwise we can save BIG */
10289   D(emitcode(";", "genDjnz"););
10290
10291   lbl = newiTempLabel (NULL);
10292   lbl1 = newiTempLabel (NULL);
10293
10294   aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10295
10296   if (AOP_NEEDSACC(IC_RESULT(ic)))
10297   {
10298       /* If the result is accessed indirectly via
10299        * the accumulator, we must explicitly write
10300        * it back after the decrement.
10301        */
10302       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, TRUE);
10303       
10304       if (strcmp(rByte, "a"))
10305       {
10306            /* Something is hopelessly wrong */
10307            fprintf(stderr, "*** warning: internal error at %s:%d\n",
10308                    __FILE__, __LINE__);
10309            /* We can just give up; the generated code will be inefficient,
10310             * but what the hey.
10311             */
10312            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10313            return 0;
10314       }
10315       emitcode ("dec", "%s", rByte);
10316       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
10317       emitcode ("jnz", "%05d$", lbl->key + 100);
10318   }
10319   else if (IS_AOP_PREG (IC_RESULT (ic)))
10320     {
10321       emitcode ("dec", "%s",
10322                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10323       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE));
10324       emitcode ("jnz", "%05d$", lbl->key + 100);
10325     }
10326   else
10327     {
10328       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE),
10329                 lbl->key + 100);
10330     }
10331   emitcode ("sjmp", "%05d$", lbl1->key + 100);
10332   emitcode ("", "%05d$:", lbl->key + 100);
10333   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10334   emitcode ("", "%05d$:", lbl1->key + 100);
10335
10336   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10337   ifx->generated = 1;
10338   return 1;
10339 }
10340
10341 /*-----------------------------------------------------------------*/
10342 /* genReceive - generate code for a receive iCode                  */
10343 /*-----------------------------------------------------------------*/
10344 static void
10345 genReceive (iCode * ic)
10346 {
10347
10348   D (emitcode (";", "genReceive ");
10349     );
10350
10351   if (isOperandInFarSpace (IC_RESULT (ic)) &&
10352       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10353        IS_TRUE_SYMOP (IC_RESULT (ic))))
10354     {
10355       int size = getSize (operandType (IC_RESULT (ic)));
10356       int offset = fReturnSizeDS390 - size;
10357       while (size--)
10358         {
10359           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ?
10360                             fReturn[fReturnSizeDS390 - offset - 1] : "acc"));
10361           offset++;
10362         }
10363       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10364       size = AOP_SIZE (IC_RESULT (ic));
10365       offset = 0;
10366       while (size--)
10367         {
10368           emitcode ("pop", "acc");
10369           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
10370         }
10371
10372     }
10373   else
10374     {
10375       _G.accInUse++;
10376       aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10377       _G.accInUse--;
10378       assignResultValue (IC_RESULT (ic));
10379     }
10380
10381   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10382 }
10383
10384 /*-----------------------------------------------------------------*/
10385 /* gen390Code - generate code for Dallas 390 based controllers     */
10386 /*-----------------------------------------------------------------*/
10387 void
10388 gen390Code (iCode * lic)
10389 {
10390   iCode *ic;
10391   int cln = 0;
10392
10393   lineHead = lineCurr = NULL;
10394
10395   if (options.model == MODEL_FLAT24) {
10396     fReturnSizeDS390 = 5;
10397     fReturn = fReturn24;
10398   } else {
10399     fReturnSizeDS390 = 4;
10400     fReturn = fReturn16;
10401     options.stack10bit=0;
10402   }
10403 #if 0
10404   //REMOVE ME!!!
10405   /* print the allocation information */
10406   if (allocInfo)
10407     printAllocInfo (currFunc, codeOutFile);
10408 #endif
10409   /* if debug information required */
10410   if (options.debug && currFunc)
10411     {
10412       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
10413       _G.debugLine = 1;
10414       if (IS_STATIC (currFunc->etype))
10415         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
10416       else
10417         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
10418       _G.debugLine = 0;
10419     }
10420   /* stack pointer name */
10421   if (options.useXstack)
10422     spname = "_spx";
10423   else
10424     spname = "sp";
10425
10426
10427   for (ic = lic; ic; ic = ic->next)
10428     {
10429
10430       if (cln != ic->lineno)
10431         {
10432           if (options.debug)
10433             {
10434               _G.debugLine = 1;
10435               emitcode ("", "C$%s$%d$%d$%d ==.",
10436                         FileBaseName (ic->filename), ic->lineno,
10437                         ic->level, ic->block);
10438               _G.debugLine = 0;
10439             }
10440           emitcode (";", "%s %d", ic->filename, ic->lineno);
10441           cln = ic->lineno;
10442         }
10443       /* if the result is marked as
10444          spilt and rematerializable or code for
10445          this has already been generated then
10446          do nothing */
10447       if (resultRemat (ic) || ic->generated)
10448         continue;
10449
10450       /* depending on the operation */
10451       switch (ic->op)
10452         {
10453         case '!':
10454           genNot (ic);
10455           break;
10456
10457         case '~':
10458           genCpl (ic);
10459           break;
10460
10461         case UNARYMINUS:
10462           genUminus (ic);
10463           break;
10464
10465         case IPUSH:
10466           genIpush (ic);
10467           break;
10468
10469         case IPOP:
10470           /* IPOP happens only when trying to restore a
10471              spilt live range, if there is an ifx statement
10472              following this pop then the if statement might
10473              be using some of the registers being popped which
10474              would destory the contents of the register so
10475              we need to check for this condition and handle it */
10476           if (ic->next &&
10477               ic->next->op == IFX &&
10478               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10479             genIfx (ic->next, ic);
10480           else
10481             genIpop (ic);
10482           break;
10483
10484         case CALL:
10485           genCall (ic);
10486           break;
10487
10488         case PCALL:
10489           genPcall (ic);
10490           break;
10491
10492         case FUNCTION:
10493           genFunction (ic);
10494           break;
10495
10496         case ENDFUNCTION:
10497           genEndFunction (ic);
10498           break;
10499
10500         case RETURN:
10501           genRet (ic);
10502           break;
10503
10504         case LABEL:
10505           genLabel (ic);
10506           break;
10507
10508         case GOTO:
10509           genGoto (ic);
10510           break;
10511
10512         case '+':
10513           genPlus (ic);
10514           break;
10515
10516         case '-':
10517           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10518             genMinus (ic);
10519           break;
10520
10521         case '*':
10522           genMult (ic);
10523           break;
10524
10525         case '/':
10526           genDiv (ic);
10527           break;
10528
10529         case '%':
10530           genMod (ic);
10531           break;
10532
10533         case '>':
10534           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10535           break;
10536
10537         case '<':
10538           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10539           break;
10540
10541         case LE_OP:
10542         case GE_OP:
10543         case NE_OP:
10544
10545           /* note these two are xlated by algebraic equivalence
10546              during parsing SDCC.y */
10547           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10548                   "got '>=' or '<=' shouldn't have come here");
10549           break;
10550
10551         case EQ_OP:
10552           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10553           break;
10554
10555         case AND_OP:
10556           genAndOp (ic);
10557           break;
10558
10559         case OR_OP:
10560           genOrOp (ic);
10561           break;
10562
10563         case '^':
10564           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10565           break;
10566
10567         case '|':
10568           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10569           break;
10570
10571         case BITWISEAND:
10572           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10573           break;
10574
10575         case INLINEASM:
10576           genInline (ic);
10577           break;
10578
10579         case RRC:
10580           genRRC (ic);
10581           break;
10582
10583         case RLC:
10584           genRLC (ic);
10585           break;
10586
10587         case GETHBIT:
10588           genGetHbit (ic);
10589           break;
10590
10591         case LEFT_OP:
10592           genLeftShift (ic);
10593           break;
10594
10595         case RIGHT_OP:
10596           genRightShift (ic);
10597           break;
10598
10599         case GET_VALUE_AT_ADDRESS:
10600           genPointerGet (ic);
10601           break;
10602
10603         case '=':
10604           if (POINTER_SET (ic))
10605             genPointerSet (ic);
10606           else
10607             genAssign (ic);
10608           break;
10609
10610         case IFX:
10611           genIfx (ic, NULL);
10612           break;
10613
10614         case ADDRESS_OF:
10615           genAddrOf (ic);
10616           break;
10617
10618         case JUMPTABLE:
10619           genJumpTab (ic);
10620           break;
10621
10622         case CAST:
10623           genCast (ic);
10624           break;
10625
10626         case RECEIVE:
10627           genReceive (ic);
10628           break;
10629
10630         case SEND:
10631           addSet (&_G.sendSet, ic);
10632           break;
10633
10634         case ARRAYINIT:
10635             genArrayInit(ic);
10636             break;
10637             
10638         default:
10639           ic = ic;
10640         }
10641     }
10642
10643
10644   /* now we are ready to call the
10645      peep hole optimizer */
10646   if (!options.nopeep)
10647     peepHole (&lineHead);
10648
10649   /* now do the actual printing */
10650   printLine (lineHead, codeOutFile);
10651   return;
10652 }