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