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