Added simple assertions to help bug tracking
[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 (0);
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 (0);
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 (0);
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 (0);
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 (0);
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             emitcode ("add", "a,#0x%02x",
3256                       (unsigned int) (lit & 0x0FFL));
3257           else
3258             emitcode ("addc", "a,#0x%02x",
3259                       (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3260         }
3261       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3262     }
3263
3264   adjustArithmeticResult (ic);
3265
3266 release:
3267   freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3268   freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3269   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3270 }
3271
3272
3273 /*-----------------------------------------------------------------*/
3274 /* genMultbits :- multiplication of bits                           */
3275 /*-----------------------------------------------------------------*/
3276 static void
3277 genMultbits (operand * left,
3278              operand * right,
3279              operand * result)
3280 {
3281   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3282   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3283   outBitC (result);
3284 }
3285
3286
3287 /*-----------------------------------------------------------------*/
3288 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
3289 /*-----------------------------------------------------------------*/
3290 static void
3291 genMultOneByte (operand * left,
3292                 operand * right,
3293                 operand * result)
3294 {
3295   sym_link *opetype = operandType (result);
3296   symbol *lbl;
3297   int size=AOP_SIZE(result);
3298
3299   if (size<1 || size>2) {
3300     // this should never happen
3301       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3302                AOP_SIZE(result), __FILE__, lineno);
3303       exit (1);
3304   }
3305
3306   /* (if two literals: the value is computed before) */
3307   /* if one literal, literal on the right */
3308   if (AOP_TYPE (left) == AOP_LIT)
3309     {
3310       operand *t = right;
3311       right = left;
3312       left = t;
3313       //emitcode (";", "swapped left and right");
3314     }
3315
3316   if (SPEC_USIGN(opetype)
3317       // ignore the sign of left and right, what else can we do?
3318       || (SPEC_USIGN(operandType(left)) && 
3319           SPEC_USIGN(operandType(right)))) {
3320     // just an unsigned 8*8=8/16 multiply
3321     //emitcode (";","unsigned");
3322     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3323     MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3324     emitcode ("mul", "ab");
3325     aopPut (AOP (result), "a", 0);
3326     if (size==2) {
3327       aopPut (AOP (result), "b", 1);
3328     }
3329     return;
3330   }
3331
3332   // we have to do a signed multiply
3333
3334   //emitcode (";", "signed");
3335   emitcode ("clr", "F0"); // reset sign flag
3336   MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3337
3338   lbl=newiTempLabel(NULL);
3339   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
3340   // left side is negative, 8-bit two's complement, this fails for -128
3341   emitcode ("setb", "F0"); // set sign flag
3342   emitcode ("cpl", "a");
3343   emitcode ("inc", "a");
3344
3345   emitcode ("", "%05d$:", lbl->key+100);
3346
3347   /* if literal */
3348   if (AOP_TYPE(right)==AOP_LIT) {
3349     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3350     /* AND literal negative */
3351     if (val < 0) {
3352       emitcode ("cpl", "F0"); // complement sign flag
3353       emitcode ("mov", "b,#0x%02x", -val);
3354     } else {
3355       emitcode ("mov", "b,#0x%02x", val);
3356     }
3357   } else {
3358     lbl=newiTempLabel(NULL);
3359     emitcode ("mov", "b,a");
3360     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3361     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3362     // right side is negative, 8-bit two's complement
3363     emitcode ("cpl", "F0"); // complement sign flag
3364     emitcode ("cpl", "a");
3365     emitcode ("inc", "a");
3366     emitcode ("", "%05d$:", lbl->key+100);
3367   }
3368   emitcode ("mul", "ab");
3369     
3370   lbl=newiTempLabel(NULL);
3371   emitcode ("jnb", "F0,%05d$", lbl->key+100);
3372   // only ONE op was negative, we have to do a 8/16-bit two's complement
3373   emitcode ("cpl", "a"); // lsb
3374   if (size==1) {
3375     emitcode ("inc", "a");
3376   } else {
3377     emitcode ("add", "a,#1");
3378     emitcode ("xch", "a,b");
3379     emitcode ("cpl", "a"); // msb
3380     emitcode ("addc", "a,#0");
3381     emitcode ("xch", "a,b");
3382   }
3383
3384   emitcode ("", "%05d$:", lbl->key+100);
3385   aopPut (AOP (result), "a", 0);
3386   if (size==2) {
3387     aopPut (AOP (result), "b", 1);
3388   }
3389 }
3390
3391 /*-----------------------------------------------------------------*/
3392 /* genMult - generates code for multiplication                     */
3393 /*-----------------------------------------------------------------*/
3394 static void
3395 genMult (iCode * ic)
3396 {
3397   operand *left = IC_LEFT (ic);
3398   operand *right = IC_RIGHT (ic);
3399   operand *result = IC_RESULT (ic);
3400
3401   /* assign the amsops */
3402   aopOp (left, ic, FALSE);
3403   aopOp (right, ic, FALSE);
3404   aopOp (result, ic, TRUE);
3405
3406   /* special cases first */
3407   /* both are bits */
3408   if (AOP_TYPE (left) == AOP_CRY &&
3409       AOP_TYPE (right) == AOP_CRY)
3410     {
3411       genMultbits (left, right, result);
3412       goto release;
3413     }
3414
3415   /* if both are of size == 1 */
3416   if (AOP_SIZE (left) == 1 &&
3417       AOP_SIZE (right) == 1)
3418     {
3419       genMultOneByte (left, right, result);
3420       goto release;
3421     }
3422
3423   /* should have been converted to function call */
3424   assert (1);
3425
3426 release:
3427   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3428   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3429   freeAsmop (result, NULL, ic, TRUE);
3430 }
3431
3432 /*-----------------------------------------------------------------*/
3433 /* genDivbits :- division of bits                                  */
3434 /*-----------------------------------------------------------------*/
3435 static void
3436 genDivbits (operand * left,
3437             operand * right,
3438             operand * result)
3439 {
3440
3441   char *l;
3442
3443   /* the result must be bit */
3444   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3445   l = aopGet (AOP (left), 0, FALSE, FALSE);
3446
3447   MOVA (l);
3448
3449   emitcode ("div", "ab");
3450   emitcode ("rrc", "a");
3451   aopPut (AOP (result), "c", 0);
3452 }
3453
3454 /*-----------------------------------------------------------------*/
3455 /* genDivOneByte : 8 bit division                                  */
3456 /*-----------------------------------------------------------------*/
3457 static void
3458 genDivOneByte (operand * left,
3459                operand * right,
3460                operand * result)
3461 {
3462   sym_link *opetype = operandType (result);
3463   char *l;
3464   symbol *lbl;
3465   int size, offset;
3466
3467   size = AOP_SIZE (result) - 1;
3468   offset = 1;
3469   /* signed or unsigned */
3470   if (SPEC_USIGN (opetype))
3471     {
3472       /* unsigned is easy */
3473       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3474       l = aopGet (AOP (left), 0, FALSE, FALSE);
3475       MOVA (l);
3476       emitcode ("div", "ab");
3477       aopPut (AOP (result), "a", 0);
3478       while (size--)
3479         aopPut (AOP (result), zero, offset++);
3480       return;
3481     }
3482
3483   /* signed is a little bit more difficult */
3484
3485   /* save the signs of the operands */
3486   l = aopGet (AOP (left), 0, FALSE, FALSE);
3487   MOVA (l);
3488   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3489   emitcode ("push", "acc");     /* save it on the stack */
3490
3491   /* now sign adjust for both left & right */
3492   l = aopGet (AOP (right), 0, FALSE, FALSE);
3493   MOVA (l);
3494   lbl = newiTempLabel (NULL);
3495   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3496   emitcode ("cpl", "a");
3497   emitcode ("inc", "a");
3498   emitcode ("", "%05d$:", (lbl->key + 100));
3499   emitcode ("mov", "b,a");
3500
3501   /* sign adjust left side */
3502   l = aopGet (AOP (left), 0, FALSE, FALSE);
3503   MOVA (l);
3504
3505   lbl = newiTempLabel (NULL);
3506   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3507   emitcode ("cpl", "a");
3508   emitcode ("inc", "a");
3509   emitcode ("", "%05d$:", (lbl->key + 100));
3510
3511   /* now the division */
3512   emitcode ("div", "ab");
3513   /* we are interested in the lower order
3514      only */
3515   emitcode ("mov", "b,a");
3516   lbl = newiTempLabel (NULL);
3517   emitcode ("pop", "acc");
3518   /* if there was an over flow we don't
3519      adjust the sign of the result */
3520   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3521   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3522   CLRC;
3523   emitcode ("clr", "a");
3524   emitcode ("subb", "a,b");
3525   emitcode ("mov", "b,a");
3526   emitcode ("", "%05d$:", (lbl->key + 100));
3527
3528   /* now we are done */
3529   aopPut (AOP (result), "b", 0);
3530   if (size > 0)
3531     {
3532       emitcode ("mov", "c,b.7");
3533       emitcode ("subb", "a,acc");
3534     }
3535   while (size--)
3536     aopPut (AOP (result), "a", offset++);
3537
3538 }
3539
3540 /*-----------------------------------------------------------------*/
3541 /* genDiv - generates code for division                            */
3542 /*-----------------------------------------------------------------*/
3543 static void
3544 genDiv (iCode * ic)
3545 {
3546   operand *left = IC_LEFT (ic);
3547   operand *right = IC_RIGHT (ic);
3548   operand *result = IC_RESULT (ic);
3549
3550   /* assign the amsops */
3551   aopOp (left, ic, FALSE);
3552   aopOp (right, ic, FALSE);
3553   aopOp (result, ic, TRUE);
3554
3555   /* special cases first */
3556   /* both are bits */
3557   if (AOP_TYPE (left) == AOP_CRY &&
3558       AOP_TYPE (right) == AOP_CRY)
3559     {
3560       genDivbits (left, right, result);
3561       goto release;
3562     }
3563
3564   /* if both are of size == 1 */
3565   if (AOP_SIZE (left) == 1 &&
3566       AOP_SIZE (right) == 1)
3567     {
3568       genDivOneByte (left, right, result);
3569       goto release;
3570     }
3571
3572   /* should have been converted to function call */
3573   assert (1);
3574 release:
3575   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3576   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3577   freeAsmop (result, NULL, ic, TRUE);
3578 }
3579
3580 /*-----------------------------------------------------------------*/
3581 /* genModbits :- modulus of bits                                   */
3582 /*-----------------------------------------------------------------*/
3583 static void
3584 genModbits (operand * left,
3585             operand * right,
3586             operand * result)
3587 {
3588
3589   char *l;
3590
3591   /* the result must be bit */
3592   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3593   l = aopGet (AOP (left), 0, FALSE, FALSE);
3594
3595   MOVA (l);
3596
3597   emitcode ("div", "ab");
3598   emitcode ("mov", "a,b");
3599   emitcode ("rrc", "a");
3600   aopPut (AOP (result), "c", 0);
3601 }
3602
3603 /*-----------------------------------------------------------------*/
3604 /* genModOneByte : 8 bit modulus                                   */
3605 /*-----------------------------------------------------------------*/
3606 static void
3607 genModOneByte (operand * left,
3608                operand * right,
3609                operand * result)
3610 {
3611   sym_link *opetype = operandType (result);
3612   char *l;
3613   symbol *lbl;
3614
3615   /* signed or unsigned */
3616   if (SPEC_USIGN (opetype))
3617     {
3618       /* unsigned is easy */
3619       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3620       l = aopGet (AOP (left), 0, FALSE, FALSE);
3621       MOVA (l);
3622       emitcode ("div", "ab");
3623       aopPut (AOP (result), "b", 0);
3624       return;
3625     }
3626
3627   /* signed is a little bit more difficult */
3628
3629   /* save the signs of the operands */
3630   l = aopGet (AOP (left), 0, FALSE, FALSE);
3631   MOVA (l);
3632
3633   emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3634   emitcode ("push", "acc");     /* save it on the stack */
3635
3636   /* now sign adjust for both left & right */
3637   l = aopGet (AOP (right), 0, FALSE, FALSE);
3638   MOVA (l);
3639
3640   lbl = newiTempLabel (NULL);
3641   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3642   emitcode ("cpl", "a");
3643   emitcode ("inc", "a");
3644   emitcode ("", "%05d$:", (lbl->key + 100));
3645   emitcode ("mov", "b,a");
3646
3647   /* sign adjust left side */
3648   l = aopGet (AOP (left), 0, FALSE, FALSE);
3649   MOVA (l);
3650
3651   lbl = newiTempLabel (NULL);
3652   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3653   emitcode ("cpl", "a");
3654   emitcode ("inc", "a");
3655   emitcode ("", "%05d$:", (lbl->key + 100));
3656
3657   /* now the multiplication */
3658   emitcode ("div", "ab");
3659   /* we are interested in the lower order
3660      only */
3661   lbl = newiTempLabel (NULL);
3662   emitcode ("pop", "acc");
3663   /* if there was an over flow we don't
3664      adjust the sign of the result */
3665   emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3666   emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3667   CLRC;
3668   emitcode ("clr", "a");
3669   emitcode ("subb", "a,b");
3670   emitcode ("mov", "b,a");
3671   emitcode ("", "%05d$:", (lbl->key + 100));
3672
3673   /* now we are done */
3674   aopPut (AOP (result), "b", 0);
3675
3676 }
3677
3678 /*-----------------------------------------------------------------*/
3679 /* genMod - generates code for division                            */
3680 /*-----------------------------------------------------------------*/
3681 static void
3682 genMod (iCode * ic)
3683 {
3684   operand *left = IC_LEFT (ic);
3685   operand *right = IC_RIGHT (ic);
3686   operand *result = IC_RESULT (ic);
3687
3688   /* assign the amsops */
3689   aopOp (left, ic, FALSE);
3690   aopOp (right, ic, FALSE);
3691   aopOp (result, ic, TRUE);
3692
3693   /* special cases first */
3694   /* both are bits */
3695   if (AOP_TYPE (left) == AOP_CRY &&
3696       AOP_TYPE (right) == AOP_CRY)
3697     {
3698       genModbits (left, right, result);
3699       goto release;
3700     }
3701
3702   /* if both are of size == 1 */
3703   if (AOP_SIZE (left) == 1 &&
3704       AOP_SIZE (right) == 1)
3705     {
3706       genModOneByte (left, right, result);
3707       goto release;
3708     }
3709
3710   /* should have been converted to function call */
3711   assert (1);
3712
3713 release:
3714   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3715   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3716   freeAsmop (result, NULL, ic, TRUE);
3717 }
3718
3719 /*-----------------------------------------------------------------*/
3720 /* genIfxJump :- will create a jump depending on the ifx           */
3721 /*-----------------------------------------------------------------*/
3722 static void
3723 genIfxJump (iCode * ic, char *jval)
3724 {
3725   symbol *jlbl;
3726   symbol *tlbl = newiTempLabel (NULL);
3727   char *inst;
3728
3729   /* if true label then we jump if condition
3730      supplied is true */
3731   if (IC_TRUE (ic))
3732     {
3733       jlbl = IC_TRUE (ic);
3734       inst = ((strcmp (jval, "a") == 0 ? "jz" :
3735                (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3736     }
3737   else
3738     {
3739       /* false label is present */
3740       jlbl = IC_FALSE (ic);
3741       inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3742                (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3743     }
3744   if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3745     emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3746   else
3747     emitcode (inst, "%05d$", tlbl->key + 100);
3748   emitcode ("ljmp", "%05d$", jlbl->key + 100);
3749   emitcode ("", "%05d$:", tlbl->key + 100);
3750
3751   /* mark the icode as generated */
3752   ic->generated = 1;
3753 }
3754
3755 /*-----------------------------------------------------------------*/
3756 /* genCmp :- greater or less than comparison                       */
3757 /*-----------------------------------------------------------------*/
3758 static void
3759 genCmp (operand * left, operand * right,
3760         operand * result, iCode * ifx, int sign, iCode *ic)
3761 {
3762   int size, offset = 0;
3763   unsigned long lit = 0L;
3764
3765   /* if left & right are bit variables */
3766   if (AOP_TYPE (left) == AOP_CRY &&
3767       AOP_TYPE (right) == AOP_CRY)
3768     {
3769       emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3770       emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3771     }
3772   else
3773     {
3774       /* subtract right from left if at the
3775          end the carry flag is set then we know that
3776          left is greater than right */
3777       size = max (AOP_SIZE (left), AOP_SIZE (right));
3778
3779       /* if unsigned char cmp with lit, do cjne left,#right,zz */
3780       if ((size == 1) && !sign &&
3781           (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3782         {
3783           symbol *lbl = newiTempLabel (NULL);
3784           emitcode ("cjne", "%s,%s,%05d$",
3785                     aopGet (AOP (left), offset, FALSE, FALSE),
3786                     aopGet (AOP (right), offset, FALSE, FALSE),
3787                     lbl->key + 100);
3788           emitcode ("", "%05d$:", lbl->key + 100);
3789         }
3790       else
3791         {
3792           if (AOP_TYPE (right) == AOP_LIT)
3793             {
3794               lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3795               /* optimize if(x < 0) or if(x >= 0) */
3796               if (lit == 0L)
3797                 {
3798                   if (!sign)
3799                     {
3800                       CLRC;
3801                     }
3802                   else
3803                     {
3804                       MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3805                       if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3806                         {
3807                           genIfxJump (ifx, "acc.7");
3808                           return;
3809                         }
3810                       else
3811                         emitcode ("rlc", "a");
3812                     }
3813                   goto release;
3814                 }
3815             }
3816           CLRC;
3817           while (size--)
3818             {
3819               MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3820               if (sign && size == 0)
3821                 {
3822                   emitcode ("xrl", "a,#0x80");
3823                   if (AOP_TYPE (right) == AOP_LIT)
3824                     {
3825                       unsigned long lit = (unsigned long)
3826                       floatFromVal (AOP (right)->aopu.aop_lit);
3827                       emitcode ("subb", "a,#0x%02x",
3828                                 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3829                     }
3830                   else
3831                     {
3832                       emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3833                       emitcode ("xrl", "b,#0x80");
3834                       emitcode ("subb", "a,b");
3835                     }
3836                 }
3837               else
3838                 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3839             }
3840         }
3841     }
3842
3843 release:
3844   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3845   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3846   if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3847     {
3848       outBitC (result);
3849     }
3850   else
3851     {
3852       /* if the result is used in the next
3853          ifx conditional branch then generate
3854          code a little differently */
3855       if (ifx)
3856         genIfxJump (ifx, "c");
3857       else
3858         outBitC (result);
3859       /* leave the result in acc */
3860     }
3861 }
3862
3863 /*-----------------------------------------------------------------*/
3864 /* genCmpGt :- greater than comparison                             */
3865 /*-----------------------------------------------------------------*/
3866 static void
3867 genCmpGt (iCode * ic, iCode * ifx)
3868 {
3869   operand *left, *right, *result;
3870   sym_link *letype, *retype;
3871   int sign;
3872
3873   left = IC_LEFT (ic);
3874   right = IC_RIGHT (ic);
3875   result = IC_RESULT (ic);
3876
3877   letype = getSpec (operandType (left));
3878   retype = getSpec (operandType (right));
3879   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3880   /* assign the amsops */
3881   aopOp (left, ic, FALSE);
3882   aopOp (right, ic, FALSE);
3883   aopOp (result, ic, TRUE);
3884
3885   genCmp (right, left, result, ifx, sign,ic);
3886
3887   freeAsmop (result, NULL, ic, TRUE);
3888 }
3889
3890 /*-----------------------------------------------------------------*/
3891 /* genCmpLt - less than comparisons                                */
3892 /*-----------------------------------------------------------------*/
3893 static void
3894 genCmpLt (iCode * ic, iCode * ifx)
3895 {
3896   operand *left, *right, *result;
3897   sym_link *letype, *retype;
3898   int sign;
3899
3900   left = IC_LEFT (ic);
3901   right = IC_RIGHT (ic);
3902   result = IC_RESULT (ic);
3903
3904   letype = getSpec (operandType (left));
3905   retype = getSpec (operandType (right));
3906   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3907
3908   /* assign the amsops */
3909   aopOp (left, ic, FALSE);
3910   aopOp (right, ic, FALSE);
3911   aopOp (result, ic, TRUE);
3912
3913   genCmp (left, right, result, ifx, sign,ic);
3914
3915   freeAsmop (result, NULL, ic, TRUE);
3916 }
3917
3918 /*-----------------------------------------------------------------*/
3919 /* gencjneshort - compare and jump if not equal                    */
3920 /*-----------------------------------------------------------------*/
3921 static void
3922 gencjneshort (operand * left, operand * right, symbol * lbl)
3923 {
3924   int size = max (AOP_SIZE (left), AOP_SIZE (right));
3925   int offset = 0;
3926   unsigned long lit = 0L;
3927
3928   /* if the left side is a literal or
3929      if the right is in a pointer register and left
3930      is not */
3931   if ((AOP_TYPE (left) == AOP_LIT) ||
3932       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3933     {
3934       operand *t = right;
3935       right = left;
3936       left = t;
3937     }
3938   if (AOP_TYPE (right) == AOP_LIT)
3939     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3940
3941   /* if the right side is a literal then anything goes */
3942   if (AOP_TYPE (right) == AOP_LIT &&
3943       AOP_TYPE (left) != AOP_DIR)
3944     {
3945       while (size--)
3946         {
3947           emitcode ("cjne", "%s,%s,%05d$",
3948                     aopGet (AOP (left), offset, FALSE, FALSE),
3949                     aopGet (AOP (right), offset, FALSE, FALSE),
3950                     lbl->key + 100);
3951           offset++;
3952         }
3953     }
3954
3955   /* if the right side is in a register or in direct space or
3956      if the left is a pointer register & right is not */
3957   else if (AOP_TYPE (right) == AOP_REG ||
3958            AOP_TYPE (right) == AOP_DIR ||
3959            (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
3960            (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
3961     {
3962       while (size--)
3963         {
3964           MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3965           if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
3966               ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
3967             emitcode ("jnz", "%05d$", lbl->key + 100);
3968           else
3969             emitcode ("cjne", "a,%s,%05d$",
3970                       aopGet (AOP (right), offset, FALSE, TRUE),
3971                       lbl->key + 100);
3972           offset++;
3973         }
3974     }
3975   else
3976     {
3977       /* right is a pointer reg need both a & b */
3978       while (size--)
3979         {
3980           char *l = aopGet (AOP (left), offset, FALSE, FALSE);
3981           if (strcmp (l, "b"))
3982             emitcode ("mov", "b,%s", l);
3983           MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
3984           emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
3985           offset++;
3986         }
3987     }
3988 }
3989
3990 /*-----------------------------------------------------------------*/
3991 /* gencjne - compare and jump if not equal                         */
3992 /*-----------------------------------------------------------------*/
3993 static void
3994 gencjne (operand * left, operand * right, symbol * lbl)
3995 {
3996   symbol *tlbl = newiTempLabel (NULL);
3997
3998   gencjneshort (left, right, lbl);
3999
4000   emitcode ("mov", "a,%s", one);
4001   emitcode ("sjmp", "%05d$", tlbl->key + 100);
4002   emitcode ("", "%05d$:", lbl->key + 100);
4003   emitcode ("clr", "a");
4004   emitcode ("", "%05d$:", tlbl->key + 100);
4005 }
4006
4007 /*-----------------------------------------------------------------*/
4008 /* genCmpEq - generates code for equal to                          */
4009 /*-----------------------------------------------------------------*/
4010 static void
4011 genCmpEq (iCode * ic, iCode * ifx)
4012 {
4013   operand *left, *right, *result;
4014
4015   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4016   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4017   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4018
4019   /* if literal, literal on the right or
4020      if the right is in a pointer register and left
4021      is not */
4022   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4023       (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4024     {
4025       operand *t = IC_RIGHT (ic);
4026       IC_RIGHT (ic) = IC_LEFT (ic);
4027       IC_LEFT (ic) = t;
4028     }
4029
4030   if (ifx && !AOP_SIZE (result))
4031     {
4032       symbol *tlbl;
4033       /* if they are both bit variables */
4034       if (AOP_TYPE (left) == AOP_CRY &&
4035           ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4036         {
4037           if (AOP_TYPE (right) == AOP_LIT)
4038             {
4039               unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4040               if (lit == 0L)
4041                 {
4042                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4043                   emitcode ("cpl", "c");
4044                 }
4045               else if (lit == 1L)
4046                 {
4047                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4048                 }
4049               else
4050                 {
4051                   emitcode ("clr", "c");
4052                 }
4053               /* AOP_TYPE(right) == AOP_CRY */
4054             }
4055           else
4056             {
4057               symbol *lbl = newiTempLabel (NULL);
4058               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4059               emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4060               emitcode ("cpl", "c");
4061               emitcode ("", "%05d$:", (lbl->key + 100));
4062             }
4063           /* if true label then we jump if condition
4064              supplied is true */
4065           tlbl = newiTempLabel (NULL);
4066           if (IC_TRUE (ifx))
4067             {
4068               emitcode ("jnc", "%05d$", tlbl->key + 100);
4069               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4070             }
4071           else
4072             {
4073               emitcode ("jc", "%05d$", tlbl->key + 100);
4074               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4075             }
4076           emitcode ("", "%05d$:", tlbl->key + 100);
4077         }
4078       else
4079         {
4080           tlbl = newiTempLabel (NULL);
4081           gencjneshort (left, right, tlbl);
4082           if (IC_TRUE (ifx))
4083             {
4084               emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4085               emitcode ("", "%05d$:", tlbl->key + 100);
4086             }
4087           else
4088             {
4089               symbol *lbl = newiTempLabel (NULL);
4090               emitcode ("sjmp", "%05d$", lbl->key + 100);
4091               emitcode ("", "%05d$:", tlbl->key + 100);
4092               emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4093               emitcode ("", "%05d$:", lbl->key + 100);
4094             }
4095         }
4096       /* mark the icode as generated */
4097       ifx->generated = 1;
4098       goto release;
4099     }
4100
4101   /* if they are both bit variables */
4102   if (AOP_TYPE (left) == AOP_CRY &&
4103       ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4104     {
4105       if (AOP_TYPE (right) == AOP_LIT)
4106         {
4107           unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4108           if (lit == 0L)
4109             {
4110               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4111               emitcode ("cpl", "c");
4112             }
4113           else if (lit == 1L)
4114             {
4115               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4116             }
4117           else
4118             {
4119               emitcode ("clr", "c");
4120             }
4121           /* AOP_TYPE(right) == AOP_CRY */
4122         }
4123       else
4124         {
4125           symbol *lbl = newiTempLabel (NULL);
4126           emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4127           emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4128           emitcode ("cpl", "c");
4129           emitcode ("", "%05d$:", (lbl->key + 100));
4130         }
4131       /* c = 1 if egal */
4132       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4133         {
4134           outBitC (result);
4135           goto release;
4136         }
4137       if (ifx)
4138         {
4139           genIfxJump (ifx, "c");
4140           goto release;
4141         }
4142       /* if the result is used in an arithmetic operation
4143          then put the result in place */
4144       outBitC (result);
4145     }
4146   else
4147     {
4148       gencjne (left, right, newiTempLabel (NULL));
4149       if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4150         {
4151           aopPut (AOP (result), "a", 0);
4152           goto release;
4153         }
4154       if (ifx)
4155         {
4156           genIfxJump (ifx, "a");
4157           goto release;
4158         }
4159       /* if the result is used in an arithmetic operation
4160          then put the result in place */
4161       if (AOP_TYPE (result) != AOP_CRY)
4162         outAcc (result);
4163       /* leave the result in acc */
4164     }
4165
4166 release:
4167   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4168   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4169   freeAsmop (result, NULL, ic, TRUE);
4170 }
4171
4172 /*-----------------------------------------------------------------*/
4173 /* ifxForOp - returns the icode containing the ifx for operand     */
4174 /*-----------------------------------------------------------------*/
4175 static iCode *
4176 ifxForOp (operand * op, iCode * ic)
4177 {
4178   /* if true symbol then needs to be assigned */
4179   if (IS_TRUE_SYMOP (op))
4180     return NULL;
4181
4182   /* if this has register type condition and
4183      the next instruction is ifx with the same operand
4184      and live to of the operand is upto the ifx only then */
4185   if (ic->next &&
4186       ic->next->op == IFX &&
4187       IC_COND (ic->next)->key == op->key &&
4188       OP_SYMBOL (op)->liveTo <= ic->next->seq)
4189     return ic->next;
4190
4191   return NULL;
4192 }
4193
4194 /*-----------------------------------------------------------------*/
4195 /* hasInc - operand is incremented before any other use            */
4196 /*-----------------------------------------------------------------*/
4197 static iCode *
4198 hasInc (operand *op, iCode *ic)
4199 {
4200   sym_link *type = operandType(op);
4201   sym_link *retype = getSpec (type);
4202   iCode *lic = ic->next;
4203   int isize ;
4204   
4205   if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4206   isize = getSize(type->next);
4207   while (lic) {
4208     /* if operand of the form op = op + <sizeof *op> */
4209     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4210         isOperandEqual(IC_RESULT(lic),op) && 
4211         isOperandLiteral(IC_RIGHT(lic)) &&
4212         operandLitValue(IC_RIGHT(lic)) == isize) {
4213       return lic;
4214     }
4215     /* if the operand used or deffed */
4216     if (bitVectBitValue(ic->uses,op->key) || (unsigned) ic->defKey == op->key) {
4217       return NULL;
4218     }
4219     lic = lic->next;
4220   }
4221   return NULL;
4222 }
4223
4224 /*-----------------------------------------------------------------*/
4225 /* genAndOp - for && operation                                     */
4226 /*-----------------------------------------------------------------*/
4227 static void
4228 genAndOp (iCode * ic)
4229 {
4230   operand *left, *right, *result;
4231   symbol *tlbl;
4232
4233   /* note here that && operations that are in an
4234      if statement are taken away by backPatchLabels
4235      only those used in arthmetic operations remain */
4236   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4237   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4238   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4239
4240   /* if both are bit variables */
4241   if (AOP_TYPE (left) == AOP_CRY &&
4242       AOP_TYPE (right) == AOP_CRY)
4243     {
4244       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4245       emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4246       outBitC (result);
4247     }
4248   else
4249     {
4250       tlbl = newiTempLabel (NULL);
4251       toBoolean (left);
4252       emitcode ("jz", "%05d$", tlbl->key + 100);
4253       toBoolean (right);
4254       emitcode ("", "%05d$:", tlbl->key + 100);
4255       outBitAcc (result);
4256     }
4257
4258   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4259   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4260   freeAsmop (result, NULL, ic, TRUE);
4261 }
4262
4263
4264 /*-----------------------------------------------------------------*/
4265 /* genOrOp - for || operation                                      */
4266 /*-----------------------------------------------------------------*/
4267 static void
4268 genOrOp (iCode * ic)
4269 {
4270   operand *left, *right, *result;
4271   symbol *tlbl;
4272
4273   /* note here that || operations that are in an
4274      if statement are taken away by backPatchLabels
4275      only those used in arthmetic operations remain */
4276   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4277   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4278   aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4279
4280   /* if both are bit variables */
4281   if (AOP_TYPE (left) == AOP_CRY &&
4282       AOP_TYPE (right) == AOP_CRY)
4283     {
4284       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4285       emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4286       outBitC (result);
4287     }
4288   else
4289     {
4290       tlbl = newiTempLabel (NULL);
4291       toBoolean (left);
4292       emitcode ("jnz", "%05d$", tlbl->key + 100);
4293       toBoolean (right);
4294       emitcode ("", "%05d$:", tlbl->key + 100);
4295       outBitAcc (result);
4296     }
4297
4298   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4299   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4300   freeAsmop (result, NULL, ic, TRUE);
4301 }
4302
4303 /*-----------------------------------------------------------------*/
4304 /* isLiteralBit - test if lit == 2^n                               */
4305 /*-----------------------------------------------------------------*/
4306 static int
4307 isLiteralBit (unsigned long lit)
4308 {
4309   unsigned long pw[32] =
4310   {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4311    0x100L, 0x200L, 0x400L, 0x800L,
4312    0x1000L, 0x2000L, 0x4000L, 0x8000L,
4313    0x10000L, 0x20000L, 0x40000L, 0x80000L,
4314    0x100000L, 0x200000L, 0x400000L, 0x800000L,
4315    0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4316    0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4317   int idx;
4318
4319   for (idx = 0; idx < 32; idx++)
4320     if (lit == pw[idx])
4321       return idx + 1;
4322   return 0;
4323 }
4324
4325 /*-----------------------------------------------------------------*/
4326 /* continueIfTrue -                                                */
4327 /*-----------------------------------------------------------------*/
4328 static void
4329 continueIfTrue (iCode * ic)
4330 {
4331   if (IC_TRUE (ic))
4332     emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4333   ic->generated = 1;
4334 }
4335
4336 /*-----------------------------------------------------------------*/
4337 /* jmpIfTrue -                                                     */
4338 /*-----------------------------------------------------------------*/
4339 static void
4340 jumpIfTrue (iCode * ic)
4341 {
4342   if (!IC_TRUE (ic))
4343     emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4344   ic->generated = 1;
4345 }
4346
4347 /*-----------------------------------------------------------------*/
4348 /* jmpTrueOrFalse -                                                */
4349 /*-----------------------------------------------------------------*/
4350 static void
4351 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4352 {
4353   // ugly but optimized by peephole
4354   if (IC_TRUE (ic))
4355     {
4356       symbol *nlbl = newiTempLabel (NULL);
4357       emitcode ("sjmp", "%05d$", nlbl->key + 100);
4358       emitcode ("", "%05d$:", tlbl->key + 100);
4359       emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4360       emitcode ("", "%05d$:", nlbl->key + 100);
4361     }
4362   else
4363     {
4364       emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4365       emitcode ("", "%05d$:", tlbl->key + 100);
4366     }
4367   ic->generated = 1;
4368 }
4369
4370 /*-----------------------------------------------------------------*/
4371 /* genAnd  - code for and                                          */
4372 /*-----------------------------------------------------------------*/
4373 static void
4374 genAnd (iCode * ic, iCode * ifx)
4375 {
4376   operand *left, *right, *result;
4377   int size, offset = 0;
4378   unsigned long lit = 0L;
4379   int bytelit = 0;
4380   char buffer[10];
4381
4382   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4383   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4384   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4385
4386 #ifdef DEBUG_TYPE
4387   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4388             AOP_TYPE (result),
4389             AOP_TYPE (left), AOP_TYPE (right));
4390   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4391             AOP_SIZE (result),
4392             AOP_SIZE (left), AOP_SIZE (right));
4393 #endif
4394
4395   /* if left is a literal & right is not then exchange them */
4396   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4397       AOP_NEEDSACC (left))
4398     {
4399       operand *tmp = right;
4400       right = left;
4401       left = tmp;
4402     }
4403
4404   /* if result = right then exchange them */
4405   if (sameRegs (AOP (result), AOP (right)))
4406     {
4407       operand *tmp = right;
4408       right = left;
4409       left = tmp;
4410     }
4411
4412   /* if right is bit then exchange them */
4413   if (AOP_TYPE (right) == AOP_CRY &&
4414       AOP_TYPE (left) != AOP_CRY)
4415     {
4416       operand *tmp = right;
4417       right = left;
4418       left = tmp;
4419     }
4420   if (AOP_TYPE (right) == AOP_LIT)
4421     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4422
4423   size = AOP_SIZE (result);
4424
4425   // if(bit & yy)
4426   // result = bit & yy;
4427   if (AOP_TYPE (left) == AOP_CRY)
4428     {
4429       // c = bit & literal;
4430       if (AOP_TYPE (right) == AOP_LIT)
4431         {
4432           if (lit & 1)
4433             {
4434               if (size && sameRegs (AOP (result), AOP (left)))
4435                 // no change
4436                 goto release;
4437               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4438             }
4439           else
4440             {
4441               // bit(result) = 0;
4442               if (size && (AOP_TYPE (result) == AOP_CRY))
4443                 {
4444                   emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4445                   goto release;
4446                 }
4447               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4448                 {
4449                   jumpIfTrue (ifx);
4450                   goto release;
4451                 }
4452               emitcode ("clr", "c");
4453             }
4454         }
4455       else
4456         {
4457           if (AOP_TYPE (right) == AOP_CRY)
4458             {
4459               // c = bit & bit;
4460               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4461               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4462             }
4463           else
4464             {
4465               // c = bit & val;
4466               MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4467               // c = lsb
4468               emitcode ("rrc", "a");
4469               emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4470             }
4471         }
4472       // bit = c
4473       // val = c
4474       if (size)
4475         outBitC (result);
4476       // if(bit & ...)
4477       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4478         genIfxJump (ifx, "c");
4479       goto release;
4480     }
4481
4482   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
4483   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
4484   if ((AOP_TYPE (right) == AOP_LIT) &&
4485       (AOP_TYPE (result) == AOP_CRY) &&
4486       (AOP_TYPE (left) != AOP_CRY))
4487     {
4488       int posbit = isLiteralBit (lit);
4489       /* left &  2^n */
4490       if (posbit)
4491         {
4492           posbit--;
4493           MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4494           // bit = left & 2^n
4495           if (size)
4496             emitcode ("mov", "c,acc.%d", posbit & 0x07);
4497           // if(left &  2^n)
4498           else
4499             {
4500               if (ifx)
4501                 {
4502                   sprintf (buffer, "acc.%d", posbit & 0x07);
4503                   genIfxJump (ifx, buffer);
4504                 }
4505               goto release;
4506             }
4507         }
4508       else
4509         {
4510           symbol *tlbl = newiTempLabel (NULL);
4511           int sizel = AOP_SIZE (left);
4512           if (size)
4513             emitcode ("setb", "c");
4514           while (sizel--)
4515             {
4516               if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4517                 {
4518                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4519                   // byte ==  2^n ?
4520                   if ((posbit = isLiteralBit (bytelit)) != 0)
4521                     emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4522                   else
4523                     {
4524                       if (bytelit != 0x0FFL)
4525                         emitcode ("anl", "a,%s",
4526                                   aopGet (AOP (right), offset, FALSE, TRUE));
4527                       emitcode ("jnz", "%05d$", tlbl->key + 100);
4528                     }
4529                 }
4530               offset++;
4531             }
4532           // bit = left & literal
4533           if (size)
4534             {
4535               emitcode ("clr", "c");
4536               emitcode ("", "%05d$:", tlbl->key + 100);
4537             }
4538           // if(left & literal)
4539           else
4540             {
4541               if (ifx)
4542                 jmpTrueOrFalse (ifx, tlbl);
4543               goto release;
4544             }
4545         }
4546       outBitC (result);
4547       goto release;
4548     }
4549
4550   /* if left is same as result */
4551   if (sameRegs (AOP (result), AOP (left)))
4552     {
4553       for (; size--; offset++)
4554         {
4555           if (AOP_TYPE (right) == AOP_LIT)
4556             {
4557               if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4558                 continue;
4559               else if (bytelit == 0)
4560                 aopPut (AOP (result), zero, offset);
4561               else if (IS_AOP_PREG (result))
4562                 {
4563                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4564                   emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4565                   aopPut (AOP (result), "a", offset);
4566                 }
4567               else
4568                 emitcode ("anl", "%s,%s",
4569                           aopGet (AOP (left), offset, FALSE, TRUE),
4570                           aopGet (AOP (right), offset, FALSE, FALSE));
4571             }
4572           else
4573             {
4574               if (AOP_TYPE (left) == AOP_ACC)
4575                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4576               else
4577                 {
4578                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4579                   if (IS_AOP_PREG (result))
4580                     {
4581                       emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4582                       aopPut (AOP (result), "a", offset);
4583
4584                     }
4585                   else
4586                     emitcode ("anl", "%s,a",
4587                               aopGet (AOP (left), offset, FALSE, TRUE));
4588                 }
4589             }
4590         }
4591     }
4592   else
4593     {
4594       // left & result in different registers
4595       if (AOP_TYPE (result) == AOP_CRY)
4596         {
4597           // result = bit
4598           // if(size), result in bit
4599           // if(!size && ifx), conditional oper: if(left & right)
4600           symbol *tlbl = newiTempLabel (NULL);
4601           int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4602           if (size)
4603             emitcode ("setb", "c");
4604           while (sizer--)
4605             {
4606               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4607                 emitcode ("anl", "a,%s",
4608                           aopGet (AOP (right), offset, FALSE, FALSE));
4609               } else {
4610                 if (AOP_TYPE(left)==AOP_ACC) {
4611                   emitcode("mov", "b,a");
4612                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4613                   emitcode("anl", "a,b");
4614                 }else {
4615                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4616                   emitcode ("anl", "a,%s",
4617                             aopGet (AOP (left), offset, FALSE, FALSE));
4618                 }
4619               }
4620               emitcode ("jnz", "%05d$", tlbl->key + 100);
4621               offset++;
4622             }
4623           if (size)
4624             {
4625               CLRC;
4626               emitcode ("", "%05d$:", tlbl->key + 100);
4627               outBitC (result);
4628             }
4629           else if (ifx)
4630             jmpTrueOrFalse (ifx, tlbl);
4631         }
4632       else
4633         {
4634           for (; (size--); offset++)
4635             {
4636               // normal case
4637               // result = left & right
4638               if (AOP_TYPE (right) == AOP_LIT)
4639                 {
4640                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4641                     {
4642                       aopPut (AOP (result),
4643                               aopGet (AOP (left), offset, FALSE, FALSE),
4644                               offset);
4645                       continue;
4646                     }
4647                   else if (bytelit == 0)
4648                     {
4649                       aopPut (AOP (result), zero, offset);
4650                       continue;
4651                     }
4652                 }
4653               // faster than result <- left, anl result,right
4654               // and better if result is SFR
4655               if (AOP_TYPE (left) == AOP_ACC)
4656                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4657               else
4658                 {
4659                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4660                   emitcode ("anl", "a,%s",
4661                             aopGet (AOP (left), offset, FALSE, FALSE));
4662                 }
4663               aopPut (AOP (result), "a", offset);
4664             }
4665         }
4666     }
4667
4668 release:
4669   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4670   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4671   freeAsmop (result, NULL, ic, TRUE);
4672 }
4673
4674 /*-----------------------------------------------------------------*/
4675 /* genOr  - code for or                                            */
4676 /*-----------------------------------------------------------------*/
4677 static void
4678 genOr (iCode * ic, iCode * ifx)
4679 {
4680   operand *left, *right, *result;
4681   int size, offset = 0;
4682   unsigned long lit = 0L;
4683
4684   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4685   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4686   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4687
4688 #ifdef DEBUG_TYPE
4689   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4690             AOP_TYPE (result),
4691             AOP_TYPE (left), AOP_TYPE (right));
4692   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4693             AOP_SIZE (result),
4694             AOP_SIZE (left), AOP_SIZE (right));
4695 #endif
4696
4697   /* if left is a literal & right is not then exchange them */
4698   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4699       AOP_NEEDSACC (left))
4700     {
4701       operand *tmp = right;
4702       right = left;
4703       left = tmp;
4704     }
4705
4706   /* if result = right then exchange them */
4707   if (sameRegs (AOP (result), AOP (right)))
4708     {
4709       operand *tmp = right;
4710       right = left;
4711       left = tmp;
4712     }
4713
4714   /* if right is bit then exchange them */
4715   if (AOP_TYPE (right) == AOP_CRY &&
4716       AOP_TYPE (left) != AOP_CRY)
4717     {
4718       operand *tmp = right;
4719       right = left;
4720       left = tmp;
4721     }
4722   if (AOP_TYPE (right) == AOP_LIT)
4723     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4724
4725   size = AOP_SIZE (result);
4726
4727   // if(bit | yy)
4728   // xx = bit | yy;
4729   if (AOP_TYPE (left) == AOP_CRY)
4730     {
4731       if (AOP_TYPE (right) == AOP_LIT)
4732         {
4733           // c = bit & literal;
4734           if (lit)
4735             {
4736               // lit != 0 => result = 1
4737               if (AOP_TYPE (result) == AOP_CRY)
4738                 {
4739                   if (size)
4740                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4741                   else if (ifx)
4742                     continueIfTrue (ifx);
4743                   goto release;
4744                 }
4745               emitcode ("setb", "c");
4746             }
4747           else
4748             {
4749               // lit == 0 => result = left
4750               if (size && sameRegs (AOP (result), AOP (left)))
4751                 goto release;
4752               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4753             }
4754         }
4755       else
4756         {
4757           if (AOP_TYPE (right) == AOP_CRY)
4758             {
4759               // c = bit | bit;
4760               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4761               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4762             }
4763           else
4764             {
4765               // c = bit | val;
4766               symbol *tlbl = newiTempLabel (NULL);
4767               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4768                 emitcode ("setb", "c");
4769               emitcode ("jb", "%s,%05d$",
4770                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
4771               toBoolean (right);
4772               emitcode ("jnz", "%05d$", tlbl->key + 100);
4773               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4774                 {
4775                   jmpTrueOrFalse (ifx, tlbl);
4776                   goto release;
4777                 }
4778               else
4779                 {
4780                   CLRC;
4781                   emitcode ("", "%05d$:", tlbl->key + 100);
4782                 }
4783             }
4784         }
4785       // bit = c
4786       // val = c
4787       if (size)
4788         outBitC (result);
4789       // if(bit | ...)
4790       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4791         genIfxJump (ifx, "c");
4792       goto release;
4793     }
4794
4795   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
4796   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
4797   if ((AOP_TYPE (right) == AOP_LIT) &&
4798       (AOP_TYPE (result) == AOP_CRY) &&
4799       (AOP_TYPE (left) != AOP_CRY))
4800     {
4801       if (lit)
4802         {
4803           // result = 1
4804           if (size)
4805             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4806           else
4807             continueIfTrue (ifx);
4808           goto release;
4809         }
4810       else
4811         {
4812           // lit = 0, result = boolean(left)
4813           if (size)
4814             emitcode ("setb", "c");
4815           toBoolean (right);
4816           if (size)
4817             {
4818               symbol *tlbl = newiTempLabel (NULL);
4819               emitcode ("jnz", "%05d$", tlbl->key + 100);
4820               CLRC;
4821               emitcode ("", "%05d$:", tlbl->key + 100);
4822             }
4823           else
4824             {
4825               genIfxJump (ifx, "a");
4826               goto release;
4827             }
4828         }
4829       outBitC (result);
4830       goto release;
4831     }
4832
4833   /* if left is same as result */
4834   if (sameRegs (AOP (result), AOP (left)))
4835     {
4836       for (; size--; offset++)
4837         {
4838           if (AOP_TYPE (right) == AOP_LIT)
4839             {
4840               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4841                 continue;
4842               else if (IS_AOP_PREG (left))
4843                 {
4844                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4845                   emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4846                   aopPut (AOP (result), "a", offset);
4847                 }
4848               else
4849                 emitcode ("orl", "%s,%s",
4850                           aopGet (AOP (left), offset, FALSE, TRUE),
4851                           aopGet (AOP (right), offset, FALSE, FALSE));
4852             }
4853           else
4854             {
4855               if (AOP_TYPE (left) == AOP_ACC)
4856                 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4857               else
4858                 {
4859                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4860                   if (IS_AOP_PREG (left))
4861                     {
4862                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4863                       aopPut (AOP (result), "a", offset);
4864                     }
4865                   else
4866                     emitcode ("orl", "%s,a",
4867                               aopGet (AOP (left), offset, FALSE, TRUE));
4868                 }
4869             }
4870         }
4871     }
4872   else
4873     {
4874       // left & result in different registers
4875       if (AOP_TYPE (result) == AOP_CRY)
4876         {
4877           // result = bit
4878           // if(size), result in bit
4879           // if(!size && ifx), conditional oper: if(left | right)
4880           symbol *tlbl = newiTempLabel (NULL);
4881           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4882           if (size)
4883             emitcode ("setb", "c");
4884           while (sizer--)
4885             {
4886               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4887                 emitcode ("orl", "a,%s",
4888                           aopGet (AOP (right), offset, FALSE, FALSE));
4889               } else {
4890                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4891                 emitcode ("orl", "a,%s",
4892                           aopGet (AOP (left), offset, FALSE, FALSE));
4893               }
4894               emitcode ("jnz", "%05d$", tlbl->key + 100);
4895               offset++;
4896             }
4897           if (size)
4898             {
4899               CLRC;
4900               emitcode ("", "%05d$:", tlbl->key + 100);
4901               outBitC (result);
4902             }
4903           else if (ifx)
4904             jmpTrueOrFalse (ifx, tlbl);
4905         }
4906       else
4907         for (; (size--); offset++)
4908           {
4909             // normal case
4910             // result = left & right
4911             if (AOP_TYPE (right) == AOP_LIT)
4912               {
4913                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4914                   {
4915                     aopPut (AOP (result),
4916                             aopGet (AOP (left), offset, FALSE, FALSE),
4917                             offset);
4918                     continue;
4919                   }
4920               }
4921             // faster than result <- left, anl result,right
4922             // and better if result is SFR
4923             if (AOP_TYPE (left) == AOP_ACC)
4924               emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4925             else
4926               {
4927                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4928                 emitcode ("orl", "a,%s",
4929                           aopGet (AOP (left), offset, FALSE, FALSE));
4930               }
4931             aopPut (AOP (result), "a", offset);
4932           }
4933     }
4934
4935 release:
4936   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4937   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4938   freeAsmop (result, NULL, ic, TRUE);
4939 }
4940
4941 /*-----------------------------------------------------------------*/
4942 /* genXor - code for xclusive or                                   */
4943 /*-----------------------------------------------------------------*/
4944 static void
4945 genXor (iCode * ic, iCode * ifx)
4946 {
4947   operand *left, *right, *result;
4948   int size, offset = 0;
4949   unsigned long lit = 0L;
4950
4951   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4952   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4953   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4954
4955 #ifdef DEBUG_TYPE
4956   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4957             AOP_TYPE (result),
4958             AOP_TYPE (left), AOP_TYPE (right));
4959   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4960             AOP_SIZE (result),
4961             AOP_SIZE (left), AOP_SIZE (right));
4962 #endif
4963
4964   /* if left is a literal & right is not ||
4965      if left needs acc & right does not */
4966   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4967       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4968     {
4969       operand *tmp = right;
4970       right = left;
4971       left = tmp;
4972     }
4973
4974   /* if result = right then exchange them */
4975   if (sameRegs (AOP (result), AOP (right)))
4976     {
4977       operand *tmp = right;
4978       right = left;
4979       left = tmp;
4980     }
4981
4982   /* if right is bit then exchange them */
4983   if (AOP_TYPE (right) == AOP_CRY &&
4984       AOP_TYPE (left) != AOP_CRY)
4985     {
4986       operand *tmp = right;
4987       right = left;
4988       left = tmp;
4989     }
4990   if (AOP_TYPE (right) == AOP_LIT)
4991     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4992
4993   size = AOP_SIZE (result);
4994
4995   // if(bit ^ yy)
4996   // xx = bit ^ yy;
4997   if (AOP_TYPE (left) == AOP_CRY)
4998     {
4999       if (AOP_TYPE (right) == AOP_LIT)
5000         {
5001           // c = bit & literal;
5002           if (lit >> 1)
5003             {
5004               // lit>>1  != 0 => result = 1
5005               if (AOP_TYPE (result) == AOP_CRY)
5006                 {
5007                   if (size)
5008                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5009                   else if (ifx)
5010                     continueIfTrue (ifx);
5011                   goto release;
5012                 }
5013               emitcode ("setb", "c");
5014             }
5015           else
5016             {
5017               // lit == (0 or 1)
5018               if (lit == 0)
5019                 {
5020                   // lit == 0, result = left
5021                   if (size && sameRegs (AOP (result), AOP (left)))
5022                     goto release;
5023                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5024                 }
5025               else
5026                 {
5027                   // lit == 1, result = not(left)
5028                   if (size && sameRegs (AOP (result), AOP (left)))
5029                     {
5030                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5031                       goto release;
5032                     }
5033                   else
5034                     {
5035                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5036                       emitcode ("cpl", "c");
5037                     }
5038                 }
5039             }
5040
5041         }
5042       else
5043         {
5044           // right != literal
5045           symbol *tlbl = newiTempLabel (NULL);
5046           if (AOP_TYPE (right) == AOP_CRY)
5047             {
5048               // c = bit ^ bit;
5049               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5050             }
5051           else
5052             {
5053               int sizer = AOP_SIZE (right);
5054               // c = bit ^ val
5055               // if val>>1 != 0, result = 1
5056               emitcode ("setb", "c");
5057               while (sizer)
5058                 {
5059                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5060                   if (sizer == 1)
5061                     // test the msb of the lsb
5062                     emitcode ("anl", "a,#0xfe");
5063                   emitcode ("jnz", "%05d$", tlbl->key + 100);
5064                   sizer--;
5065                 }
5066               // val = (0,1)
5067               emitcode ("rrc", "a");
5068             }
5069           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5070           emitcode ("cpl", "c");
5071           emitcode ("", "%05d$:", (tlbl->key + 100));
5072         }
5073       // bit = c
5074       // val = c
5075       if (size)
5076         outBitC (result);
5077       // if(bit | ...)
5078       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5079         genIfxJump (ifx, "c");
5080       goto release;
5081     }
5082
5083   if (sameRegs (AOP (result), AOP (left)))
5084     {
5085       /* if left is same as result */
5086       for (; size--; offset++)
5087         {
5088           if (AOP_TYPE (right) == AOP_LIT)
5089             {
5090               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5091                 continue;
5092               else if (IS_AOP_PREG (left))
5093                 {
5094                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5095                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5096                   aopPut (AOP (result), "a", offset);
5097                 }
5098               else
5099                 emitcode ("xrl", "%s,%s",
5100                           aopGet (AOP (left), offset, FALSE, TRUE),
5101                           aopGet (AOP (right), offset, FALSE, FALSE));
5102             }
5103           else
5104             {
5105               if (AOP_TYPE (left) == AOP_ACC)
5106                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5107               else
5108                 {
5109                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5110                   if (IS_AOP_PREG (left))
5111                     {
5112                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5113                       aopPut (AOP (result), "a", offset);
5114                     }
5115                   else
5116                     emitcode ("xrl", "%s,a",
5117                               aopGet (AOP (left), offset, FALSE, TRUE));
5118                 }
5119             }
5120         }
5121     }
5122   else
5123     {
5124       // left & result in different registers
5125       if (AOP_TYPE (result) == AOP_CRY)
5126         {
5127           // result = bit
5128           // if(size), result in bit
5129           // if(!size && ifx), conditional oper: if(left ^ right)
5130           symbol *tlbl = newiTempLabel (NULL);
5131           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5132           if (size)
5133             emitcode ("setb", "c");
5134           while (sizer--)
5135             {
5136               if ((AOP_TYPE (right) == AOP_LIT) &&
5137                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5138                 {
5139                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5140                 }
5141               else
5142                 {
5143                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5144                     emitcode ("xrl", "a,%s",
5145                               aopGet (AOP (right), offset, FALSE, FALSE));
5146                   } else {
5147                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5148                     emitcode ("xrl", "a,%s",
5149                               aopGet (AOP (left), offset, FALSE, FALSE));
5150                   }
5151                 }
5152               emitcode ("jnz", "%05d$", tlbl->key + 100);
5153               offset++;
5154             }
5155           if (size)
5156             {
5157               CLRC;
5158               emitcode ("", "%05d$:", tlbl->key + 100);
5159               outBitC (result);
5160             }
5161           else if (ifx)
5162             jmpTrueOrFalse (ifx, tlbl);
5163         }
5164       else
5165         for (; (size--); offset++)
5166           {
5167             // normal case
5168             // result = left & right
5169             if (AOP_TYPE (right) == AOP_LIT)
5170               {
5171                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5172                   {
5173                     aopPut (AOP (result),
5174                             aopGet (AOP (left), offset, FALSE, FALSE),
5175                             offset);
5176                     continue;
5177                   }
5178               }
5179             // faster than result <- left, anl result,right
5180             // and better if result is SFR
5181             if (AOP_TYPE (left) == AOP_ACC)
5182               emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5183             else
5184               {
5185                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5186                 emitcode ("xrl", "a,%s",
5187                           aopGet (AOP (left), offset, FALSE, TRUE));
5188               }
5189             aopPut (AOP (result), "a", offset);
5190           }
5191     }
5192
5193 release:
5194   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5195   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5196   freeAsmop (result, NULL, ic, TRUE);
5197 }
5198
5199 /*-----------------------------------------------------------------*/
5200 /* genInline - write the inline code out                           */
5201 /*-----------------------------------------------------------------*/
5202 static void
5203 genInline (iCode * ic)
5204 {
5205   char *buffer, *bp, *bp1;
5206
5207   _G.inLine += (!options.asmpeep);
5208
5209   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5210   strcpy (buffer, IC_INLINE (ic));
5211
5212   /* emit each line as a code */
5213   while (*bp)
5214     {
5215       if (*bp == '\n')
5216         {
5217           *bp++ = '\0';
5218           emitcode (bp1, "");
5219           bp1 = bp;
5220         }
5221       else
5222         {
5223           if (*bp == ':')
5224             {
5225               bp++;
5226               *bp = '\0';
5227               bp++;
5228               emitcode (bp1, "");
5229               bp1 = bp;
5230             }
5231           else
5232             bp++;
5233         }
5234     }
5235   if (bp1 != bp)
5236     emitcode (bp1, "");
5237   /*     emitcode("",buffer); */
5238   _G.inLine -= (!options.asmpeep);
5239 }
5240
5241 /*-----------------------------------------------------------------*/
5242 /* genRRC - rotate right with carry                                */
5243 /*-----------------------------------------------------------------*/
5244 static void
5245 genRRC (iCode * ic)
5246 {
5247   operand *left, *result;
5248   int size, offset = 0;
5249   char *l;
5250
5251   /* rotate right with carry */
5252   left = IC_LEFT (ic);
5253   result = IC_RESULT (ic);
5254   aopOp (left, ic, FALSE);
5255   aopOp (result, ic, FALSE);
5256
5257   /* move it to the result */
5258   size = AOP_SIZE (result);
5259   offset = size - 1;
5260   CLRC;
5261   while (size--)
5262     {
5263       l = aopGet (AOP (left), offset, FALSE, FALSE);
5264       MOVA (l);
5265       emitcode ("rrc", "a");
5266       if (AOP_SIZE (result) > 1)
5267         aopPut (AOP (result), "a", offset--);
5268     }
5269   /* now we need to put the carry into the
5270      highest order byte of the result */
5271   if (AOP_SIZE (result) > 1)
5272     {
5273       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5274       MOVA (l);
5275     }
5276   emitcode ("mov", "acc.7,c");
5277   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5278   freeAsmop (left, NULL, ic, TRUE);
5279   freeAsmop (result, NULL, ic, TRUE);
5280 }
5281
5282 /*-----------------------------------------------------------------*/
5283 /* genRLC - generate code for rotate left with carry               */
5284 /*-----------------------------------------------------------------*/
5285 static void
5286 genRLC (iCode * ic)
5287 {
5288   operand *left, *result;
5289   int size, offset = 0;
5290   char *l;
5291
5292   /* rotate right with carry */
5293   left = IC_LEFT (ic);
5294   result = IC_RESULT (ic);
5295   aopOp (left, ic, FALSE);
5296   aopOp (result, ic, FALSE);
5297
5298   /* move it to the result */
5299   size = AOP_SIZE (result);
5300   offset = 0;
5301   if (size--)
5302     {
5303       l = aopGet (AOP (left), offset, FALSE, FALSE);
5304       MOVA (l);
5305       emitcode ("add", "a,acc");
5306       if (AOP_SIZE (result) > 1)
5307         aopPut (AOP (result), "a", offset++);
5308       while (size--)
5309         {
5310           l = aopGet (AOP (left), offset, FALSE, FALSE);
5311           MOVA (l);
5312           emitcode ("rlc", "a");
5313           if (AOP_SIZE (result) > 1)
5314             aopPut (AOP (result), "a", offset++);
5315         }
5316     }
5317   /* now we need to put the carry into the
5318      highest order byte of the result */
5319   if (AOP_SIZE (result) > 1)
5320     {
5321       l = aopGet (AOP (result), 0, FALSE, FALSE);
5322       MOVA (l);
5323     }
5324   emitcode ("mov", "acc.0,c");
5325   aopPut (AOP (result), "a", 0);
5326   freeAsmop (left, NULL, ic, TRUE);
5327   freeAsmop (result, NULL, ic, TRUE);
5328 }
5329
5330 /*-----------------------------------------------------------------*/
5331 /* genGetHbit - generates code get highest order bit               */
5332 /*-----------------------------------------------------------------*/
5333 static void
5334 genGetHbit (iCode * ic)
5335 {
5336   operand *left, *result;
5337   left = IC_LEFT (ic);
5338   result = IC_RESULT (ic);
5339   aopOp (left, ic, FALSE);
5340   aopOp (result, ic, FALSE);
5341
5342   /* get the highest order byte into a */
5343   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5344   if (AOP_TYPE (result) == AOP_CRY)
5345     {
5346       emitcode ("rlc", "a");
5347       outBitC (result);
5348     }
5349   else
5350     {
5351       emitcode ("rl", "a");
5352       emitcode ("anl", "a,#0x01");
5353       outAcc (result);
5354     }
5355
5356
5357   freeAsmop (left, NULL, ic, TRUE);
5358   freeAsmop (result, NULL, ic, TRUE);
5359 }
5360
5361 /*-----------------------------------------------------------------*/
5362 /* AccRol - rotate left accumulator by known count                 */
5363 /*-----------------------------------------------------------------*/
5364 static void
5365 AccRol (int shCount)
5366 {
5367   shCount &= 0x0007;            // shCount : 0..7
5368
5369   switch (shCount)
5370     {
5371     case 0:
5372       break;
5373     case 1:
5374       emitcode ("rl", "a");
5375       break;
5376     case 2:
5377       emitcode ("rl", "a");
5378       emitcode ("rl", "a");
5379       break;
5380     case 3:
5381       emitcode ("swap", "a");
5382       emitcode ("rr", "a");
5383       break;
5384     case 4:
5385       emitcode ("swap", "a");
5386       break;
5387     case 5:
5388       emitcode ("swap", "a");
5389       emitcode ("rl", "a");
5390       break;
5391     case 6:
5392       emitcode ("rr", "a");
5393       emitcode ("rr", "a");
5394       break;
5395     case 7:
5396       emitcode ("rr", "a");
5397       break;
5398     }
5399 }
5400
5401 /*-----------------------------------------------------------------*/
5402 /* AccLsh - left shift accumulator by known count                  */
5403 /*-----------------------------------------------------------------*/
5404 static void
5405 AccLsh (int shCount)
5406 {
5407   if (shCount != 0)
5408     {
5409       if (shCount == 1)
5410         emitcode ("add", "a,acc");
5411       else if (shCount == 2)
5412         {
5413           emitcode ("add", "a,acc");
5414           emitcode ("add", "a,acc");
5415         }
5416       else
5417         {
5418           /* rotate left accumulator */
5419           AccRol (shCount);
5420           /* and kill the lower order bits */
5421           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5422         }
5423     }
5424 }
5425
5426 /*-----------------------------------------------------------------*/
5427 /* AccRsh - right shift accumulator by known count                 */
5428 /*-----------------------------------------------------------------*/
5429 static void
5430 AccRsh (int shCount)
5431 {
5432   if (shCount != 0)
5433     {
5434       if (shCount == 1)
5435         {
5436           CLRC;
5437           emitcode ("rrc", "a");
5438         }
5439       else
5440         {
5441           /* rotate right accumulator */
5442           AccRol (8 - shCount);
5443           /* and kill the higher order bits */
5444           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5445         }
5446     }
5447 }
5448
5449 /*-----------------------------------------------------------------*/
5450 /* AccSRsh - signed right shift accumulator by known count                 */
5451 /*-----------------------------------------------------------------*/
5452 static void
5453 AccSRsh (int shCount)
5454 {
5455   symbol *tlbl;
5456   if (shCount != 0)
5457     {
5458       if (shCount == 1)
5459         {
5460           emitcode ("mov", "c,acc.7");
5461           emitcode ("rrc", "a");
5462         }
5463       else if (shCount == 2)
5464         {
5465           emitcode ("mov", "c,acc.7");
5466           emitcode ("rrc", "a");
5467           emitcode ("mov", "c,acc.7");
5468           emitcode ("rrc", "a");
5469         }
5470       else
5471         {
5472           tlbl = newiTempLabel (NULL);
5473           /* rotate right accumulator */
5474           AccRol (8 - shCount);
5475           /* and kill the higher order bits */
5476           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5477           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5478           emitcode ("orl", "a,#0x%02x",
5479                     (unsigned char) ~SRMask[shCount]);
5480           emitcode ("", "%05d$:", tlbl->key + 100);
5481         }
5482     }
5483 }
5484
5485 /*-----------------------------------------------------------------*/
5486 /* shiftR1Left2Result - shift right one byte from left to result   */
5487 /*-----------------------------------------------------------------*/
5488 static void
5489 shiftR1Left2Result (operand * left, int offl,
5490                     operand * result, int offr,
5491                     int shCount, int sign)
5492 {
5493   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5494   /* shift right accumulator */
5495   if (sign)
5496     AccSRsh (shCount);
5497   else
5498     AccRsh (shCount);
5499   aopPut (AOP (result), "a", offr);
5500 }
5501
5502 /*-----------------------------------------------------------------*/
5503 /* shiftL1Left2Result - shift left one byte from left to result    */
5504 /*-----------------------------------------------------------------*/
5505 static void
5506 shiftL1Left2Result (operand * left, int offl,
5507                     operand * result, int offr, int shCount)
5508 {
5509   char *l;
5510   l = aopGet (AOP (left), offl, FALSE, FALSE);
5511   MOVA (l);
5512   /* shift left accumulator */
5513   AccLsh (shCount);
5514   aopPut (AOP (result), "a", offr);
5515 }
5516
5517 /*-----------------------------------------------------------------*/
5518 /* movLeft2Result - move byte from left to result                  */
5519 /*-----------------------------------------------------------------*/
5520 static void
5521 movLeft2Result (operand * left, int offl,
5522                 operand * result, int offr, int sign)
5523 {
5524   char *l;
5525   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5526     {
5527       l = aopGet (AOP (left), offl, FALSE, FALSE);
5528
5529       if (*l == '@' && (IS_AOP_PREG (result)))
5530         {
5531           emitcode ("mov", "a,%s", l);
5532           aopPut (AOP (result), "a", offr);
5533         }
5534       else
5535         {
5536           if (!sign)
5537             aopPut (AOP (result), l, offr);
5538           else
5539             {
5540               /* MSB sign in acc.7 ! */
5541               if (getDataSize (left) == offl + 1)
5542                 {
5543                   emitcode ("mov", "a,%s", l);
5544                   aopPut (AOP (result), "a", offr);
5545                 }
5546             }
5547         }
5548     }
5549 }
5550
5551 /*-----------------------------------------------------------------*/
5552 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
5553 /*-----------------------------------------------------------------*/
5554 static void
5555 AccAXRrl1 (char *x)
5556 {
5557   emitcode ("rrc", "a");
5558   emitcode ("xch", "a,%s", x);
5559   emitcode ("rrc", "a");
5560   emitcode ("xch", "a,%s", x);
5561 }
5562
5563 /*-----------------------------------------------------------------*/
5564 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
5565 /*-----------------------------------------------------------------*/
5566 static void
5567 AccAXLrl1 (char *x)
5568 {
5569   emitcode ("xch", "a,%s", x);
5570   emitcode ("rlc", "a");
5571   emitcode ("xch", "a,%s", x);
5572   emitcode ("rlc", "a");
5573 }
5574
5575 /*-----------------------------------------------------------------*/
5576 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
5577 /*-----------------------------------------------------------------*/
5578 static void
5579 AccAXLsh1 (char *x)
5580 {
5581   emitcode ("xch", "a,%s", x);
5582   emitcode ("add", "a,acc");
5583   emitcode ("xch", "a,%s", x);
5584   emitcode ("rlc", "a");
5585 }
5586
5587 /*-----------------------------------------------------------------*/
5588 /* AccAXLsh - left shift a:x by known count (0..7)                 */
5589 /*-----------------------------------------------------------------*/
5590 static void
5591 AccAXLsh (char *x, int shCount)
5592 {
5593   switch (shCount)
5594     {
5595     case 0:
5596       break;
5597     case 1:
5598       AccAXLsh1 (x);
5599       break;
5600     case 2:
5601       AccAXLsh1 (x);
5602       AccAXLsh1 (x);
5603       break;
5604     case 3:
5605     case 4:
5606     case 5:                     // AAAAABBB:CCCCCDDD
5607
5608       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
5609
5610       emitcode ("anl", "a,#0x%02x",
5611                 SLMask[shCount]);       // BBB00000:CCCCCDDD
5612
5613       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
5614
5615       AccRol (shCount);         // DDDCCCCC:BBB00000
5616
5617       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
5618
5619       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
5620
5621       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
5622
5623       emitcode ("anl", "a,#0x%02x",
5624                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
5625
5626       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
5627
5628       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
5629
5630       break;
5631     case 6:                     // AAAAAABB:CCCCCCDD
5632       emitcode ("anl", "a,#0x%02x",
5633                 SRMask[shCount]);       // 000000BB:CCCCCCDD
5634       emitcode ("mov", "c,acc.0");      // c = B
5635       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
5636 #if 0 // REMOVE ME
5637       AccAXRrl1 (x);            // BCCCCCCD:D000000B
5638       AccAXRrl1 (x);            // BBCCCCCC:DD000000
5639 #else
5640       emitcode("rrc","a"); 
5641       emitcode("xch","a,%s", x); 
5642       emitcode("rrc","a"); 
5643       emitcode("mov","c,acc.0"); //<< get correct bit 
5644       emitcode("xch","a,%s", x); 
5645
5646       emitcode("rrc","a"); 
5647       emitcode("xch","a,%s", x); 
5648       emitcode("rrc","a"); 
5649       emitcode("xch","a,%s", x); 
5650 #endif
5651       break;
5652     case 7:                     // a:x <<= 7
5653
5654       emitcode ("anl", "a,#0x%02x",
5655                 SRMask[shCount]);       // 0000000B:CCCCCCCD
5656
5657       emitcode ("mov", "c,acc.0");      // c = B
5658
5659       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
5660
5661       AccAXRrl1 (x);            // BCCCCCCC:D0000000
5662
5663       break;
5664     default:
5665       break;
5666     }
5667 }
5668
5669 /*-----------------------------------------------------------------*/
5670 /* AccAXRsh - right shift a:x known count (0..7)                   */
5671 /*-----------------------------------------------------------------*/
5672 static void
5673 AccAXRsh (char *x, int shCount)
5674 {
5675   switch (shCount)
5676     {
5677     case 0:
5678       break;
5679     case 1:
5680       CLRC;
5681       AccAXRrl1 (x);            // 0->a:x
5682
5683       break;
5684     case 2:
5685       CLRC;
5686       AccAXRrl1 (x);            // 0->a:x
5687
5688       CLRC;
5689       AccAXRrl1 (x);            // 0->a:x
5690
5691       break;
5692     case 3:
5693     case 4:
5694     case 5:                     // AAAAABBB:CCCCCDDD = a:x
5695
5696       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
5697
5698       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
5699
5700       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
5701
5702       emitcode ("anl", "a,#0x%02x",
5703                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
5704
5705       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
5706
5707       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
5708
5709       emitcode ("anl", "a,#0x%02x",
5710                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
5711
5712       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
5713
5714       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
5715
5716       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
5717
5718       break;
5719     case 6:                     // AABBBBBB:CCDDDDDD
5720
5721       emitcode ("mov", "c,acc.7");
5722       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
5723
5724       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
5725
5726       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
5727
5728       emitcode ("anl", "a,#0x%02x",
5729                 SRMask[shCount]);       // 000000AA:BBBBBBCC
5730
5731       break;
5732     case 7:                     // ABBBBBBB:CDDDDDDD
5733
5734       emitcode ("mov", "c,acc.7");      // c = A
5735
5736       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
5737
5738       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
5739
5740       emitcode ("anl", "a,#0x%02x",
5741                 SRMask[shCount]);       // 0000000A:BBBBBBBC
5742
5743       break;
5744     default:
5745       break;
5746     }
5747 }
5748
5749 /*-----------------------------------------------------------------*/
5750 /* AccAXRshS - right shift signed a:x known count (0..7)           */
5751 /*-----------------------------------------------------------------*/
5752 static void
5753 AccAXRshS (char *x, int shCount)
5754 {
5755   symbol *tlbl;
5756   switch (shCount)
5757     {
5758     case 0:
5759       break;
5760     case 1:
5761       emitcode ("mov", "c,acc.7");
5762       AccAXRrl1 (x);            // s->a:x
5763
5764       break;
5765     case 2:
5766       emitcode ("mov", "c,acc.7");
5767       AccAXRrl1 (x);            // s->a:x
5768
5769       emitcode ("mov", "c,acc.7");
5770       AccAXRrl1 (x);            // s->a:x
5771
5772       break;
5773     case 3:
5774     case 4:
5775     case 5:                     // AAAAABBB:CCCCCDDD = a:x
5776
5777       tlbl = newiTempLabel (NULL);
5778       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
5779
5780       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
5781
5782       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
5783
5784       emitcode ("anl", "a,#0x%02x",
5785                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
5786
5787       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
5788
5789       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
5790
5791       emitcode ("anl", "a,#0x%02x",
5792                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
5793
5794       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
5795
5796       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
5797
5798       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
5799
5800       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5801       emitcode ("orl", "a,#0x%02x",
5802                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
5803
5804       emitcode ("", "%05d$:", tlbl->key + 100);
5805       break;                    // SSSSAAAA:BBBCCCCC
5806
5807     case 6:                     // AABBBBBB:CCDDDDDD
5808
5809       tlbl = newiTempLabel (NULL);
5810       emitcode ("mov", "c,acc.7");
5811       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
5812
5813       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
5814
5815       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
5816
5817       emitcode ("anl", "a,#0x%02x",
5818                 SRMask[shCount]);       // 000000AA:BBBBBBCC
5819
5820       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5821       emitcode ("orl", "a,#0x%02x",
5822                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
5823
5824       emitcode ("", "%05d$:", tlbl->key + 100);
5825       break;
5826     case 7:                     // ABBBBBBB:CDDDDDDD
5827
5828       tlbl = newiTempLabel (NULL);
5829       emitcode ("mov", "c,acc.7");      // c = A
5830
5831       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
5832
5833       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
5834
5835       emitcode ("anl", "a,#0x%02x",
5836                 SRMask[shCount]);       // 0000000A:BBBBBBBC
5837
5838       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5839       emitcode ("orl", "a,#0x%02x",
5840                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
5841
5842       emitcode ("", "%05d$:", tlbl->key + 100);
5843       break;
5844     default:
5845       break;
5846     }
5847 }
5848
5849 /*-----------------------------------------------------------------*/
5850 /* shiftL2Left2Result - shift left two bytes from left to result   */
5851 /*-----------------------------------------------------------------*/
5852 static void
5853 shiftL2Left2Result (operand * left, int offl,
5854                     operand * result, int offr, int shCount)
5855 {
5856   if (sameRegs (AOP (result), AOP (left)) &&
5857       ((offl + MSB16) == offr))
5858     {
5859       /* don't crash result[offr] */
5860       MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5861       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5862     }
5863   else
5864     {
5865       movLeft2Result (left, offl, result, offr, 0);
5866       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5867     }
5868   /* ax << shCount (x = lsb(result)) */
5869   AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5870   aopPut (AOP (result), "a", offr + MSB16);
5871 }
5872
5873
5874 /*-----------------------------------------------------------------*/
5875 /* shiftR2Left2Result - shift right two bytes from left to result  */
5876 /*-----------------------------------------------------------------*/
5877 static void
5878 shiftR2Left2Result (operand * left, int offl,
5879                     operand * result, int offr,
5880                     int shCount, int sign)
5881 {
5882   if (sameRegs (AOP (result), AOP (left)) &&
5883       ((offl + MSB16) == offr))
5884     {
5885       /* don't crash result[offr] */
5886       MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5887       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5888     }
5889   else
5890     {
5891       movLeft2Result (left, offl, result, offr, 0);
5892       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5893     }
5894   /* a:x >> shCount (x = lsb(result)) */
5895   if (sign)
5896     AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5897   else
5898     AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5899   if (getDataSize (result) > 1)
5900     aopPut (AOP (result), "a", offr + MSB16);
5901 }
5902
5903 /*-----------------------------------------------------------------*/
5904 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5905 /*-----------------------------------------------------------------*/
5906 static void
5907 shiftLLeftOrResult (operand * left, int offl,
5908                     operand * result, int offr, int shCount)
5909 {
5910   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5911   /* shift left accumulator */
5912   AccLsh (shCount);
5913   /* or with result */
5914   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5915   /* back to result */
5916   aopPut (AOP (result), "a", offr);
5917 }
5918
5919 /*-----------------------------------------------------------------*/
5920 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5921 /*-----------------------------------------------------------------*/
5922 static void
5923 shiftRLeftOrResult (operand * left, int offl,
5924                     operand * result, int offr, int shCount)
5925 {
5926   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5927   /* shift right accumulator */
5928   AccRsh (shCount);
5929   /* or with result */
5930   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5931   /* back to result */
5932   aopPut (AOP (result), "a", offr);
5933 }
5934
5935 /*-----------------------------------------------------------------*/
5936 /* genlshOne - left shift a one byte quantity by known count       */
5937 /*-----------------------------------------------------------------*/
5938 static void
5939 genlshOne (operand * result, operand * left, int shCount)
5940 {
5941   shiftL1Left2Result (left, LSB, result, LSB, shCount);
5942 }
5943
5944 /*-----------------------------------------------------------------*/
5945 /* genlshTwo - left shift two bytes by known amount != 0           */
5946 /*-----------------------------------------------------------------*/
5947 static void
5948 genlshTwo (operand * result, operand * left, int shCount)
5949 {
5950   int size;
5951
5952   size = getDataSize (result);
5953
5954   /* if shCount >= 8 */
5955   if (shCount >= 8)
5956     {
5957       shCount -= 8;
5958
5959       if (size > 1)
5960         {
5961           if (shCount)
5962             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5963           else
5964             movLeft2Result (left, LSB, result, MSB16, 0);
5965         }
5966       aopPut (AOP (result), zero, LSB);
5967     }
5968
5969   /*  1 <= shCount <= 7 */
5970   else
5971     {
5972       if (size == 1)
5973         shiftL1Left2Result (left, LSB, result, LSB, shCount);
5974       else
5975         shiftL2Left2Result (left, LSB, result, LSB, shCount);
5976     }
5977 }
5978
5979 /*-----------------------------------------------------------------*/
5980 /* shiftLLong - shift left one long from left to result            */
5981 /* offl = LSB or MSB16                                             */
5982 /*-----------------------------------------------------------------*/
5983 static void
5984 shiftLLong (operand * left, operand * result, int offr)
5985 {
5986   char *l;
5987   int size = AOP_SIZE (result);
5988
5989   if (size >= LSB + offr)
5990     {
5991       l = aopGet (AOP (left), LSB, FALSE, FALSE);
5992       MOVA (l);
5993       emitcode ("add", "a,acc");
5994       if (sameRegs (AOP (left), AOP (result)) &&
5995           size >= MSB16 + offr && offr != LSB)
5996         emitcode ("xch", "a,%s",
5997                   aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5998       else
5999         aopPut (AOP (result), "a", LSB + offr);
6000     }
6001
6002   if (size >= MSB16 + offr)
6003     {
6004       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6005         {
6006           l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6007           MOVA (l);
6008         }
6009       emitcode ("rlc", "a");
6010       if (sameRegs (AOP (left), AOP (result)) &&
6011           size >= MSB24 + offr && offr != LSB)
6012         emitcode ("xch", "a,%s",
6013                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6014       else
6015         aopPut (AOP (result), "a", MSB16 + offr);
6016     }
6017
6018   if (size >= MSB24 + offr)
6019     {
6020       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6021         {
6022           l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6023           MOVA (l);
6024         }
6025       emitcode ("rlc", "a");
6026       if (sameRegs (AOP (left), AOP (result)) &&
6027           size >= MSB32 + offr && offr != LSB)
6028         emitcode ("xch", "a,%s",
6029                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6030       else
6031         aopPut (AOP (result), "a", MSB24 + offr);
6032     }
6033
6034   if (size > MSB32 + offr)
6035     {
6036       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6037         {
6038           l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6039           MOVA (l);
6040         }
6041       emitcode ("rlc", "a");
6042       aopPut (AOP (result), "a", MSB32 + offr);
6043     }
6044   if (offr != LSB)
6045     aopPut (AOP (result), zero, LSB);
6046 }
6047
6048 /*-----------------------------------------------------------------*/
6049 /* genlshFour - shift four byte by a known amount != 0             */
6050 /*-----------------------------------------------------------------*/
6051 static void
6052 genlshFour (operand * result, operand * left, int shCount)
6053 {
6054   int size;
6055
6056   size = AOP_SIZE (result);
6057
6058   /* if shifting more that 3 bytes */
6059   if (shCount >= 24)
6060     {
6061       shCount -= 24;
6062       if (shCount)
6063         /* lowest order of left goes to the highest
6064            order of the destination */
6065         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6066       else
6067         movLeft2Result (left, LSB, result, MSB32, 0);
6068       aopPut (AOP (result), zero, LSB);
6069       aopPut (AOP (result), zero, MSB16);
6070       aopPut (AOP (result), zero, MSB24);
6071       return;
6072     }
6073
6074   /* more than two bytes */
6075   else if (shCount >= 16)
6076     {
6077       /* lower order two bytes goes to higher order two bytes */
6078       shCount -= 16;
6079       /* if some more remaining */
6080       if (shCount)
6081         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6082       else
6083         {
6084           movLeft2Result (left, MSB16, result, MSB32, 0);
6085           movLeft2Result (left, LSB, result, MSB24, 0);
6086         }
6087       aopPut (AOP (result), zero, MSB16);
6088       aopPut (AOP (result), zero, LSB);
6089       return;
6090     }
6091
6092   /* if more than 1 byte */
6093   else if (shCount >= 8)
6094     {
6095       /* lower order three bytes goes to higher order  three bytes */
6096       shCount -= 8;
6097       if (size == 2)
6098         {
6099           if (shCount)
6100             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6101           else
6102             movLeft2Result (left, LSB, result, MSB16, 0);
6103         }
6104       else
6105         {                       /* size = 4 */
6106           if (shCount == 0)
6107             {
6108               movLeft2Result (left, MSB24, result, MSB32, 0);
6109               movLeft2Result (left, MSB16, result, MSB24, 0);
6110               movLeft2Result (left, LSB, result, MSB16, 0);
6111               aopPut (AOP (result), zero, LSB);
6112             }
6113           else if (shCount == 1)
6114             shiftLLong (left, result, MSB16);
6115           else
6116             {
6117               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6118               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6119               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6120               aopPut (AOP (result), zero, LSB);
6121             }
6122         }
6123     }
6124
6125   /* 1 <= shCount <= 7 */
6126   else if (shCount <= 2)
6127     {
6128       shiftLLong (left, result, LSB);
6129       if (shCount == 2)
6130         shiftLLong (result, result, LSB);
6131     }
6132   /* 3 <= shCount <= 7, optimize */
6133   else
6134     {
6135       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6136       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6137       shiftL2Left2Result (left, LSB, result, LSB, shCount);
6138     }
6139 }
6140
6141 /*-----------------------------------------------------------------*/
6142 /* genLeftShiftLiteral - left shifting by known count              */
6143 /*-----------------------------------------------------------------*/
6144 static void
6145 genLeftShiftLiteral (operand * left,
6146                      operand * right,
6147                      operand * result,
6148                      iCode * ic)
6149 {
6150   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6151   int size;
6152
6153   freeAsmop (right, NULL, ic, TRUE);
6154
6155   aopOp (left, ic, FALSE);
6156   aopOp (result, ic, FALSE);
6157
6158   size = getSize (operandType (result));
6159
6160 #if VIEW_SIZE
6161   emitcode ("; shift left ", "result %d, left %d", size,
6162             AOP_SIZE (left));
6163 #endif
6164
6165   /* I suppose that the left size >= result size */
6166   if (shCount == 0)
6167     {
6168       while (size--)
6169         {
6170           movLeft2Result (left, size, result, size, 0);
6171         }
6172     }
6173
6174   else if (shCount >= (size * 8))
6175     while (size--)
6176       aopPut (AOP (result), zero, size);
6177   else
6178     {
6179       switch (size)
6180         {
6181         case 1:
6182           genlshOne (result, left, shCount);
6183           break;
6184
6185         case 2:
6186           genlshTwo (result, left, shCount);
6187           break;
6188
6189         case 4:
6190           genlshFour (result, left, shCount);
6191           break;
6192         default:
6193           fprintf(stderr, "*** ack! mystery literal shift!\n");
6194           break;
6195         }
6196     }
6197   freeAsmop (left, NULL, ic, TRUE);
6198   freeAsmop (result, NULL, ic, TRUE);
6199 }
6200
6201 /*-----------------------------------------------------------------*/
6202 /* genLeftShift - generates code for left shifting                 */
6203 /*-----------------------------------------------------------------*/
6204 static void
6205 genLeftShift (iCode * ic)
6206 {
6207   operand *left, *right, *result;
6208   int size, offset;
6209   char *l;
6210   symbol *tlbl, *tlbl1;
6211
6212   right = IC_RIGHT (ic);
6213   left = IC_LEFT (ic);
6214   result = IC_RESULT (ic);
6215
6216   aopOp (right, ic, FALSE);
6217
6218   /* if the shift count is known then do it
6219      as efficiently as possible */
6220   if (AOP_TYPE (right) == AOP_LIT)
6221     {
6222       genLeftShiftLiteral (left, right, result, ic);
6223       return;
6224     }
6225
6226   /* shift count is unknown then we have to form
6227      a loop get the loop count in B : Note: we take
6228      only the lower order byte since shifting
6229      more that 32 bits make no sense anyway, ( the
6230      largest size of an object can be only 32 bits ) */
6231
6232   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6233   emitcode ("inc", "b");
6234   freeAsmop (right, NULL, ic, TRUE);
6235   aopOp (left, ic, FALSE);
6236   aopOp (result, ic, FALSE);
6237
6238   /* now move the left to the result if they are not the
6239      same */
6240   if (!sameRegs (AOP (left), AOP (result)) &&
6241       AOP_SIZE (result) > 1)
6242     {
6243
6244       size = AOP_SIZE (result);
6245       offset = 0;
6246       while (size--)
6247         {
6248           l = aopGet (AOP (left), offset, FALSE, TRUE);
6249           if (*l == '@' && (IS_AOP_PREG (result)))
6250             {
6251
6252               emitcode ("mov", "a,%s", l);
6253               aopPut (AOP (result), "a", offset);
6254             }
6255           else
6256             aopPut (AOP (result), l, offset);
6257           offset++;
6258         }
6259     }
6260
6261   tlbl = newiTempLabel (NULL);
6262   size = AOP_SIZE (result);
6263   offset = 0;
6264   tlbl1 = newiTempLabel (NULL);
6265
6266   /* if it is only one byte then */
6267   if (size == 1)
6268     {
6269       symbol *tlbl1 = newiTempLabel (NULL);
6270
6271       l = aopGet (AOP (left), 0, FALSE, FALSE);
6272       MOVA (l);
6273       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6274       emitcode ("", "%05d$:", tlbl->key + 100);
6275       emitcode ("add", "a,acc");
6276       emitcode ("", "%05d$:", tlbl1->key + 100);
6277       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6278       aopPut (AOP (result), "a", 0);
6279       goto release;
6280     }
6281
6282   reAdjustPreg (AOP (result));
6283
6284   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6285   emitcode ("", "%05d$:", tlbl->key + 100);
6286   l = aopGet (AOP (result), offset, FALSE, FALSE);
6287   MOVA (l);
6288   emitcode ("add", "a,acc");
6289   aopPut (AOP (result), "a", offset++);
6290   while (--size)
6291     {
6292       l = aopGet (AOP (result), offset, FALSE, FALSE);
6293       MOVA (l);
6294       emitcode ("rlc", "a");
6295       aopPut (AOP (result), "a", offset++);
6296     }
6297   reAdjustPreg (AOP (result));
6298
6299   emitcode ("", "%05d$:", tlbl1->key + 100);
6300   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6301 release:
6302   freeAsmop (left, NULL, ic, TRUE);
6303   freeAsmop (result, NULL, ic, TRUE);
6304 }
6305
6306 /*-----------------------------------------------------------------*/
6307 /* genrshOne - right shift a one byte quantity by known count      */
6308 /*-----------------------------------------------------------------*/
6309 static void
6310 genrshOne (operand * result, operand * left,
6311            int shCount, int sign)
6312 {
6313   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6314 }
6315
6316 /*-----------------------------------------------------------------*/
6317 /* genrshTwo - right shift two bytes by known amount != 0          */
6318 /*-----------------------------------------------------------------*/
6319 static void
6320 genrshTwo (operand * result, operand * left,
6321            int shCount, int sign)
6322 {
6323   /* if shCount >= 8 */
6324   if (shCount >= 8)
6325     {
6326       shCount -= 8;
6327       if (shCount)
6328         shiftR1Left2Result (left, MSB16, result, LSB,
6329                             shCount, sign);
6330       else
6331         movLeft2Result (left, MSB16, result, LSB, sign);
6332       addSign (result, MSB16, sign);
6333     }
6334
6335   /*  1 <= shCount <= 7 */
6336   else
6337     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6338 }
6339
6340 /*-----------------------------------------------------------------*/
6341 /* shiftRLong - shift right one long from left to result           */
6342 /* offl = LSB or MSB16                                             */
6343 /*-----------------------------------------------------------------*/
6344 static void
6345 shiftRLong (operand * left, int offl,
6346             operand * result, int sign)
6347 {
6348   int isSameRegs=sameRegs(AOP(left),AOP(result));
6349
6350   if (isSameRegs && offl>1) {
6351     // we are in big trouble, but this shouldn't happen
6352     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6353   }
6354
6355   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6356   
6357   if (offl==MSB16) {
6358     // shift is > 8
6359     if (sign) {
6360       emitcode ("rlc", "a");
6361       emitcode ("subb", "a,acc");
6362       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6363     } else {
6364       aopPut (AOP(result), zero, MSB32);
6365     }
6366   }
6367
6368   if (!sign) {
6369     emitcode ("clr", "c");
6370   } else {
6371     emitcode ("mov", "c,acc.7");
6372   }
6373
6374   emitcode ("rrc", "a");
6375
6376   if (isSameRegs && offl==MSB16) {
6377     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6378   } else {
6379     aopPut (AOP (result), "a", MSB32);
6380     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6381   }
6382
6383   emitcode ("rrc", "a");
6384   if (isSameRegs && offl==1) {
6385     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6386   } else {
6387     aopPut (AOP (result), "a", MSB24);
6388     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6389   }
6390   emitcode ("rrc", "a");
6391   aopPut (AOP (result), "a", MSB16 - offl);
6392
6393   if (offl == LSB)
6394     {
6395       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6396       emitcode ("rrc", "a");
6397       aopPut (AOP (result), "a", LSB);
6398     }
6399 }
6400
6401 /*-----------------------------------------------------------------*/
6402 /* genrshFour - shift four byte by a known amount != 0             */
6403 /*-----------------------------------------------------------------*/
6404 static void
6405 genrshFour (operand * result, operand * left,
6406             int shCount, int sign)
6407 {
6408   /* if shifting more that 3 bytes */
6409   if (shCount >= 24)
6410     {
6411       shCount -= 24;
6412       if (shCount)
6413         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6414       else
6415         movLeft2Result (left, MSB32, result, LSB, sign);
6416       addSign (result, MSB16, sign);
6417     }
6418   else if (shCount >= 16)
6419     {
6420       shCount -= 16;
6421       if (shCount)
6422         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6423       else
6424         {
6425           movLeft2Result (left, MSB24, result, LSB, 0);
6426           movLeft2Result (left, MSB32, result, MSB16, sign);
6427         }
6428       addSign (result, MSB24, sign);
6429     }
6430   else if (shCount >= 8)
6431     {
6432       shCount -= 8;
6433       if (shCount == 1)
6434         shiftRLong (left, MSB16, result, sign);
6435       else if (shCount == 0)
6436         {
6437           movLeft2Result (left, MSB16, result, LSB, 0);
6438           movLeft2Result (left, MSB24, result, MSB16, 0);
6439           movLeft2Result (left, MSB32, result, MSB24, sign);
6440           addSign (result, MSB32, sign);
6441         }
6442       else
6443         {
6444           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6445           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6446           /* the last shift is signed */
6447           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6448           addSign (result, MSB32, sign);
6449         }
6450     }
6451   else
6452     {                           /* 1 <= shCount <= 7 */
6453       if (shCount <= 2)
6454         {
6455           shiftRLong (left, LSB, result, sign);
6456           if (shCount == 2)
6457             shiftRLong (result, LSB, result, sign);
6458         }
6459       else
6460         {
6461           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6462           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6463           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6464         }
6465     }
6466 }
6467
6468 /*-----------------------------------------------------------------*/
6469 /* genRightShiftLiteral - right shifting by known count            */
6470 /*-----------------------------------------------------------------*/
6471 static void
6472 genRightShiftLiteral (operand * left,
6473                       operand * right,
6474                       operand * result,
6475                       iCode * ic,
6476                       int sign)
6477 {
6478   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6479   int size;
6480
6481   freeAsmop (right, NULL, ic, TRUE);
6482
6483   aopOp (left, ic, FALSE);
6484   aopOp (result, ic, FALSE);
6485
6486 #if VIEW_SIZE
6487   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6488             AOP_SIZE (left));
6489 #endif
6490
6491   size = getDataSize (left);
6492   /* test the LEFT size !!! */
6493
6494   /* I suppose that the left size >= result size */
6495   if (shCount == 0)
6496     {
6497       size = getDataSize (result);
6498       while (size--)
6499         movLeft2Result (left, size, result, size, 0);
6500     }
6501
6502   else if (shCount >= (size * 8))
6503     {
6504       if (sign)
6505         /* get sign in acc.7 */
6506         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6507       addSign (result, LSB, sign);
6508     }
6509   else
6510     {
6511       switch (size)
6512         {
6513         case 1:
6514           genrshOne (result, left, shCount, sign);
6515           break;
6516
6517         case 2:
6518           genrshTwo (result, left, shCount, sign);
6519           break;
6520
6521         case 4:
6522           genrshFour (result, left, shCount, sign);
6523           break;
6524         default:
6525           break;
6526         }
6527
6528       freeAsmop (left, NULL, ic, TRUE);
6529       freeAsmop (result, NULL, ic, TRUE);
6530     }
6531 }
6532
6533 /*-----------------------------------------------------------------*/
6534 /* genSignedRightShift - right shift of signed number              */
6535 /*-----------------------------------------------------------------*/
6536 static void
6537 genSignedRightShift (iCode * ic)
6538 {
6539   operand *right, *left, *result;
6540   int size, offset;
6541   char *l;
6542   symbol *tlbl, *tlbl1;
6543
6544   /* we do it the hard way put the shift count in b
6545      and loop thru preserving the sign */
6546
6547   right = IC_RIGHT (ic);
6548   left = IC_LEFT (ic);
6549   result = IC_RESULT (ic);
6550
6551   aopOp (right, ic, FALSE);
6552
6553
6554   if (AOP_TYPE (right) == AOP_LIT)
6555     {
6556       genRightShiftLiteral (left, right, result, ic, 1);
6557       return;
6558     }
6559   /* shift count is unknown then we have to form
6560      a loop get the loop count in B : Note: we take
6561      only the lower order byte since shifting
6562      more that 32 bits make no sense anyway, ( the
6563      largest size of an object can be only 32 bits ) */
6564
6565   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6566   emitcode ("inc", "b");
6567   freeAsmop (right, NULL, ic, TRUE);
6568   aopOp (left, ic, FALSE);
6569   aopOp (result, ic, FALSE);
6570
6571   /* now move the left to the result if they are not the
6572      same */
6573   if (!sameRegs (AOP (left), AOP (result)) &&
6574       AOP_SIZE (result) > 1)
6575     {
6576
6577       size = AOP_SIZE (result);
6578       offset = 0;
6579       while (size--)
6580         {
6581           l = aopGet (AOP (left), offset, FALSE, TRUE);
6582           if (*l == '@' && IS_AOP_PREG (result))
6583             {
6584
6585               emitcode ("mov", "a,%s", l);
6586               aopPut (AOP (result), "a", offset);
6587             }
6588           else
6589             aopPut (AOP (result), l, offset);
6590           offset++;
6591         }
6592     }
6593
6594   /* mov the highest order bit to OVR */
6595   tlbl = newiTempLabel (NULL);
6596   tlbl1 = newiTempLabel (NULL);
6597
6598   size = AOP_SIZE (result);
6599   offset = size - 1;
6600   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6601   emitcode ("rlc", "a");
6602   emitcode ("mov", "ov,c");
6603   /* if it is only one byte then */
6604   if (size == 1)
6605     {
6606       l = aopGet (AOP (left), 0, FALSE, FALSE);
6607       MOVA (l);
6608       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6609       emitcode ("", "%05d$:", tlbl->key + 100);
6610       emitcode ("mov", "c,ov");
6611       emitcode ("rrc", "a");
6612       emitcode ("", "%05d$:", tlbl1->key + 100);
6613       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6614       aopPut (AOP (result), "a", 0);
6615       goto release;
6616     }
6617
6618   reAdjustPreg (AOP (result));
6619   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6620   emitcode ("", "%05d$:", tlbl->key + 100);
6621   emitcode ("mov", "c,ov");
6622   while (size--)
6623     {
6624       l = aopGet (AOP (result), offset, FALSE, FALSE);
6625       MOVA (l);
6626       emitcode ("rrc", "a");
6627       aopPut (AOP (result), "a", offset--);
6628     }
6629   reAdjustPreg (AOP (result));
6630   emitcode ("", "%05d$:", tlbl1->key + 100);
6631   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6632
6633 release:
6634   freeAsmop (left, NULL, ic, TRUE);
6635   freeAsmop (result, NULL, ic, TRUE);
6636 }
6637
6638 /*-----------------------------------------------------------------*/
6639 /* genRightShift - generate code for right shifting                */
6640 /*-----------------------------------------------------------------*/
6641 static void
6642 genRightShift (iCode * ic)
6643 {
6644   operand *right, *left, *result;
6645   sym_link *retype;
6646   int size, offset;
6647   char *l;
6648   symbol *tlbl, *tlbl1;
6649
6650   /* if signed then we do it the hard way preserve the
6651      sign bit moving it inwards */
6652   retype = getSpec (operandType (IC_RESULT (ic)));
6653
6654   if (!SPEC_USIGN (retype))
6655     {
6656       genSignedRightShift (ic);
6657       return;
6658     }
6659
6660   /* signed & unsigned types are treated the same : i.e. the
6661      signed is NOT propagated inwards : quoting from the
6662      ANSI - standard : "for E1 >> E2, is equivalent to division
6663      by 2**E2 if unsigned or if it has a non-negative value,
6664      otherwise the result is implementation defined ", MY definition
6665      is that the sign does not get propagated */
6666
6667   right = IC_RIGHT (ic);
6668   left = IC_LEFT (ic);
6669   result = IC_RESULT (ic);
6670
6671   aopOp (right, ic, FALSE);
6672
6673   /* if the shift count is known then do it
6674      as efficiently as possible */
6675   if (AOP_TYPE (right) == AOP_LIT)
6676     {
6677       genRightShiftLiteral (left, right, result, ic, 0);
6678       return;
6679     }
6680
6681   /* shift count is unknown then we have to form
6682      a loop get the loop count in B : Note: we take
6683      only the lower order byte since shifting
6684      more that 32 bits make no sense anyway, ( the
6685      largest size of an object can be only 32 bits ) */
6686
6687   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6688   emitcode ("inc", "b");
6689   freeAsmop (right, NULL, ic, TRUE);
6690   aopOp (left, ic, FALSE);
6691   aopOp (result, ic, FALSE);
6692
6693   /* now move the left to the result if they are not the
6694      same */
6695   if (!sameRegs (AOP (left), AOP (result)) &&
6696       AOP_SIZE (result) > 1)
6697     {
6698
6699       size = AOP_SIZE (result);
6700       offset = 0;
6701       while (size--)
6702         {
6703           l = aopGet (AOP (left), offset, FALSE, TRUE);
6704           if (*l == '@' && IS_AOP_PREG (result))
6705             {
6706
6707               emitcode ("mov", "a,%s", l);
6708               aopPut (AOP (result), "a", offset);
6709             }
6710           else
6711             aopPut (AOP (result), l, offset);
6712           offset++;
6713         }
6714     }
6715
6716   tlbl = newiTempLabel (NULL);
6717   tlbl1 = newiTempLabel (NULL);
6718   size = AOP_SIZE (result);
6719   offset = size - 1;
6720
6721   /* if it is only one byte then */
6722   if (size == 1)
6723     {
6724       l = aopGet (AOP (left), 0, FALSE, FALSE);
6725       MOVA (l);
6726       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6727       emitcode ("", "%05d$:", tlbl->key + 100);
6728       CLRC;
6729       emitcode ("rrc", "a");
6730       emitcode ("", "%05d$:", tlbl1->key + 100);
6731       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6732       aopPut (AOP (result), "a", 0);
6733       goto release;
6734     }
6735
6736   reAdjustPreg (AOP (result));
6737   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6738   emitcode ("", "%05d$:", tlbl->key + 100);
6739   CLRC;
6740   while (size--)
6741     {
6742       l = aopGet (AOP (result), offset, FALSE, FALSE);
6743       MOVA (l);
6744       emitcode ("rrc", "a");
6745       aopPut (AOP (result), "a", offset--);
6746     }
6747   reAdjustPreg (AOP (result));
6748
6749   emitcode ("", "%05d$:", tlbl1->key + 100);
6750   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6751
6752 release:
6753   freeAsmop (left, NULL, ic, TRUE);
6754   freeAsmop (result, NULL, ic, TRUE);
6755 }
6756
6757 /*-----------------------------------------------------------------*/
6758 /* genUnpackBits - generates code for unpacking bits               */
6759 /*-----------------------------------------------------------------*/
6760 static void
6761 genUnpackBits (operand * result, char *rname, int ptype)
6762 {
6763   int shCnt;
6764   int rlen = 0;
6765   sym_link *etype;
6766   int offset = 0;
6767   int rsize;
6768
6769   etype = getSpec (operandType (result));
6770   rsize = getSize (operandType (result));
6771   /* read the first byte  */
6772   switch (ptype)
6773     {
6774
6775     case POINTER:
6776     case IPOINTER:
6777       emitcode ("mov", "a,@%s", rname);
6778       break;
6779
6780     case PPOINTER:
6781       emitcode ("movx", "a,@%s", rname);
6782       break;
6783
6784     case FPOINTER:
6785       emitcode ("movx", "a,@dptr");
6786       break;
6787
6788     case CPOINTER:
6789       emitcode ("clr", "a");
6790       emitcode ("movc", "a,%s", "@a+dptr");
6791       break;
6792
6793     case GPOINTER:
6794       emitcode ("lcall", "__gptrget");
6795       break;
6796     }
6797
6798   rlen = SPEC_BLEN (etype);
6799
6800   /* if we have bitdisplacement then it fits   */
6801   /* into this byte completely or if length is */
6802   /* less than a byte                          */
6803   if ((shCnt = SPEC_BSTR (etype)) ||
6804       (SPEC_BLEN (etype) <= 8))
6805     {
6806
6807       /* shift right acc */
6808       AccRsh (shCnt);
6809
6810       emitcode ("anl", "a,#0x%02x",
6811                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6812       aopPut (AOP (result), "a", offset++);
6813       goto finish;
6814     }
6815
6816   /* bit field did not fit in a byte  */
6817   aopPut (AOP (result), "a", offset++);
6818
6819   while (1)
6820     {
6821
6822       switch (ptype)
6823         {
6824         case POINTER:
6825         case IPOINTER:
6826           emitcode ("inc", "%s", rname);
6827           emitcode ("mov", "a,@%s", rname);
6828           break;
6829
6830         case PPOINTER:
6831           emitcode ("inc", "%s", rname);
6832           emitcode ("movx", "a,@%s", rname);
6833           break;
6834
6835         case FPOINTER:
6836           emitcode ("inc", "dptr");
6837           emitcode ("movx", "a,@dptr");
6838           break;
6839
6840         case CPOINTER:
6841           emitcode ("clr", "a");
6842           emitcode ("inc", "dptr");
6843           emitcode ("movc", "a", "@a+dptr");
6844           break;
6845
6846         case GPOINTER:
6847           emitcode ("inc", "dptr");
6848           emitcode ("lcall", "__gptrget");
6849           break;
6850         }
6851
6852       rlen -= 8;
6853       /* if we are done */
6854       if (rlen < 8)
6855         break;
6856
6857       aopPut (AOP (result), "a", offset++);
6858
6859     }
6860
6861   if (rlen)
6862     {
6863       //  emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6864       AccLsh (8 - rlen);
6865       aopPut (AOP (result), "a", offset++);
6866     }
6867
6868 finish:
6869   if (offset < rsize)
6870     {
6871       rsize -= offset;
6872       while (rsize--)
6873         aopPut (AOP (result), zero, offset++);
6874     }
6875   return;
6876 }
6877
6878
6879 /*-----------------------------------------------------------------*/
6880 /* genDataPointerGet - generates code when ptr offset is known     */
6881 /*-----------------------------------------------------------------*/
6882 static void
6883 genDataPointerGet (operand * left,
6884                    operand * result,
6885                    iCode * ic)
6886 {
6887   char *l;
6888   char buffer[256];
6889   int size, offset = 0;
6890   aopOp (result, ic, TRUE);
6891
6892   /* get the string representation of the name */
6893   l = aopGet (AOP (left), 0, FALSE, TRUE);
6894   size = AOP_SIZE (result);
6895   while (size--)
6896     {
6897       if (offset)
6898         sprintf (buffer, "(%s + %d)", l + 1, offset);
6899       else
6900         sprintf (buffer, "%s", l + 1);
6901       aopPut (AOP (result), buffer, offset++);
6902     }
6903
6904   freeAsmop (left, NULL, ic, TRUE);
6905   freeAsmop (result, NULL, ic, TRUE);
6906 }
6907
6908 /*-----------------------------------------------------------------*/
6909 /* genNearPointerGet - emitcode for near pointer fetch             */
6910 /*-----------------------------------------------------------------*/
6911 static void
6912 genNearPointerGet (operand * left,
6913                    operand * result,
6914                    iCode * ic,
6915                    iCode * pi)
6916 {
6917   asmop *aop = NULL;
6918   regs *preg = NULL;
6919   char *rname;
6920   sym_link *rtype, *retype;
6921   sym_link *ltype = operandType (left);
6922   char buffer[80];
6923
6924   rtype = operandType (result);
6925   retype = getSpec (rtype);
6926
6927   aopOp (left, ic, FALSE);
6928
6929   /* if left is rematerialisable and
6930      result is not bit variable type and
6931      the left is pointer to data space i.e
6932      lower 128 bytes of space */
6933   if (AOP_TYPE (left) == AOP_IMMD &&
6934       !IS_BITVAR (retype) &&
6935       DCL_TYPE (ltype) == POINTER)
6936     {
6937       genDataPointerGet (left, result, ic);
6938       return;
6939     }
6940
6941   /* if the value is already in a pointer register
6942      then don't need anything more */
6943   if (!AOP_INPREG (AOP (left)))
6944     {
6945       /* otherwise get a free pointer register */
6946       aop = newAsmop (0);
6947       preg = getFreePtr (ic, &aop, FALSE);
6948       emitcode ("mov", "%s,%s",
6949                 preg->name,
6950                 aopGet (AOP (left), 0, FALSE, TRUE));
6951       rname = preg->name;
6952     }
6953   else
6954     rname = aopGet (AOP (left), 0, FALSE, FALSE);
6955
6956   aopOp (result, ic, FALSE);
6957
6958   /* if bitfield then unpack the bits */
6959   if (IS_BITVAR (retype))
6960     genUnpackBits (result, rname, POINTER);
6961   else
6962     {
6963       /* we have can just get the values */
6964       int size = AOP_SIZE (result);
6965       int offset = 0;
6966
6967       while (size--)
6968         {
6969           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6970             {
6971
6972               emitcode ("mov", "a,@%s", rname);
6973               aopPut (AOP (result), "a", offset);
6974             }
6975           else
6976             {
6977               sprintf (buffer, "@%s", rname);
6978               aopPut (AOP (result), buffer, offset);
6979             }
6980           offset++;
6981           if (size || pi)
6982             emitcode ("inc", "%s", rname);
6983         }
6984     }
6985
6986   /* now some housekeeping stuff */
6987   if (aop)       /* we had to allocate for this iCode */
6988     {
6989       if (pi) { /* post increment present */
6990         aopPut(AOP ( left ),rname,0);
6991       }
6992       freeAsmop (NULL, aop, ic, TRUE);
6993     }
6994   else
6995     {
6996       /* we did not allocate which means left
6997          already in a pointer register, then
6998          if size > 0 && this could be used again
6999          we have to point it back to where it
7000          belongs */
7001       if ((AOP_SIZE (result) > 1 &&
7002            !OP_SYMBOL (left)->remat &&
7003            (OP_SYMBOL (left)->liveTo > ic->seq ||
7004             ic->depth)) &&
7005           !pi)
7006         {
7007           int size = AOP_SIZE (result) - 1;
7008           while (size--)
7009             emitcode ("dec", "%s", rname);
7010         }
7011     }
7012
7013   /* done */
7014   freeAsmop (left, NULL, ic, TRUE);
7015   freeAsmop (result, NULL, ic, TRUE);
7016   if (pi) pi->generated = 1;
7017 }
7018
7019 /*-----------------------------------------------------------------*/
7020 /* genPagedPointerGet - emitcode for paged pointer fetch           */
7021 /*-----------------------------------------------------------------*/
7022 static void
7023 genPagedPointerGet (operand * left,
7024                     operand * result,
7025                     iCode * ic,
7026                     iCode *pi)
7027 {
7028   asmop *aop = NULL;
7029   regs *preg = NULL;
7030   char *rname;
7031   sym_link *rtype, *retype;
7032
7033   rtype = operandType (result);
7034   retype = getSpec (rtype);
7035
7036   aopOp (left, ic, FALSE);
7037
7038   /* if the value is already in a pointer register
7039      then don't need anything more */
7040   if (!AOP_INPREG (AOP (left)))
7041     {
7042       /* otherwise get a free pointer register */
7043       aop = newAsmop (0);
7044       preg = getFreePtr (ic, &aop, FALSE);
7045       emitcode ("mov", "%s,%s",
7046                 preg->name,
7047                 aopGet (AOP (left), 0, FALSE, TRUE));
7048       rname = preg->name;
7049     }
7050   else
7051     rname = aopGet (AOP (left), 0, FALSE, FALSE);
7052
7053   aopOp (result, ic, FALSE);
7054
7055   /* if bitfield then unpack the bits */
7056   if (IS_BITVAR (retype))
7057     genUnpackBits (result, rname, PPOINTER);
7058   else
7059     {
7060       /* we have can just get the values */
7061       int size = AOP_SIZE (result);
7062       int offset = 0;
7063
7064       while (size--)
7065         {
7066
7067           emitcode ("movx", "a,@%s", rname);
7068           aopPut (AOP (result), "a", offset);
7069
7070           offset++;
7071
7072           if (size || pi)
7073             emitcode ("inc", "%s", rname);
7074         }
7075     }
7076
7077   /* now some housekeeping stuff */
7078   if (aop) /* we had to allocate for this iCode */
7079     {
7080       if (pi) aopPut ( AOP (left), rname, 0);
7081       freeAsmop (NULL, aop, ic, TRUE);
7082     }
7083   else
7084     {
7085       /* we did not allocate which means left
7086          already in a pointer register, then
7087          if size > 0 && this could be used again
7088          we have to point it back to where it
7089          belongs */
7090       if ((AOP_SIZE (result) > 1 &&
7091            !OP_SYMBOL (left)->remat &&
7092            (OP_SYMBOL (left)->liveTo > ic->seq ||
7093             ic->depth)) &&
7094           !pi)
7095         {
7096           int size = AOP_SIZE (result) - 1;
7097           while (size--)
7098             emitcode ("dec", "%s", rname);
7099         }
7100     }
7101
7102   /* done */
7103   freeAsmop (left, NULL, ic, TRUE);
7104   freeAsmop (result, NULL, ic, TRUE);
7105   if (pi) pi->generated = 1;
7106
7107 }
7108
7109 /*-----------------------------------------------------------------*/
7110 /* genFarPointerGet - gget value from far space                    */
7111 /*-----------------------------------------------------------------*/
7112 static void
7113 genFarPointerGet (operand * left,
7114                   operand * result, iCode * ic, iCode * pi)
7115 {
7116   int size, offset;
7117   sym_link *retype = getSpec (operandType (result));
7118
7119   aopOp (left, ic, FALSE);
7120
7121   /* if the operand is already in dptr
7122      then we do nothing else we move the value to dptr */
7123   if (AOP_TYPE (left) != AOP_STR)
7124     {
7125       /* if this is remateriazable */
7126       if (AOP_TYPE (left) == AOP_IMMD)
7127         emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7128       else
7129         {                       /* we need to get it byte by byte */
7130           emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7131           emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7132         }
7133     }
7134   /* so dptr know contains the address */
7135   aopOp (result, ic, FALSE);
7136
7137   /* if bit then unpack */
7138   if (IS_BITVAR (retype))
7139     genUnpackBits (result, "dptr", FPOINTER);
7140   else
7141     {
7142       size = AOP_SIZE (result);
7143       offset = 0;
7144
7145       while (size--)
7146         {
7147           emitcode ("movx", "a,@dptr");
7148           aopPut (AOP (result), "a", offset++);
7149           if (size || pi)
7150             emitcode ("inc", "dptr");
7151         }
7152     }
7153   
7154   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7155     aopPut ( AOP (left), "dpl", 0);
7156     aopPut ( AOP (left), "dph", 1);
7157     pi->generated = 1;
7158   }
7159   freeAsmop (left, NULL, ic, TRUE);
7160   freeAsmop (result, NULL, ic, TRUE);
7161 }
7162
7163 /*-----------------------------------------------------------------*/
7164 /* genCodePointerGet - gget value from code space                  */
7165 /*-----------------------------------------------------------------*/
7166 static void
7167 genCodePointerGet (operand * left,
7168                     operand * result, iCode * ic, iCode *pi)
7169 {
7170   int size, offset;
7171   sym_link *retype = getSpec (operandType (result));
7172
7173   aopOp (left, ic, FALSE);
7174
7175   /* if the operand is already in dptr
7176      then we do nothing else we move the value to dptr */
7177   if (AOP_TYPE (left) != AOP_STR)
7178     {
7179       /* if this is remateriazable */
7180       if (AOP_TYPE (left) == AOP_IMMD)
7181         emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7182       else
7183         {                       /* we need to get it byte by byte */
7184           emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7185           emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7186         }
7187     }
7188   /* so dptr know contains the address */
7189   aopOp (result, ic, FALSE);
7190
7191   /* if bit then unpack */
7192   if (IS_BITVAR (retype))
7193     genUnpackBits (result, "dptr", CPOINTER);
7194   else
7195     {
7196       size = AOP_SIZE (result);
7197       offset = 0;
7198
7199       while (size--)
7200         {
7201           emitcode ("clr", "a");
7202           emitcode ("movc", "a,@a+dptr");
7203           aopPut (AOP (result), "a", offset++);
7204           if (size || pi)
7205             emitcode ("inc", "dptr");
7206         }
7207     }
7208
7209   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7210     aopPut ( AOP (left), "dpl", 0);
7211     aopPut ( AOP (left), "dph", 1);
7212     pi->generated = 1;
7213   }
7214   freeAsmop (left, NULL, ic, TRUE);
7215   freeAsmop (result, NULL, ic, TRUE);
7216 }
7217
7218 /*-----------------------------------------------------------------*/
7219 /* genGenPointerGet - gget value from generic pointer space        */
7220 /*-----------------------------------------------------------------*/
7221 static void
7222 genGenPointerGet (operand * left,
7223                   operand * result, iCode * ic, iCode *pi)
7224 {
7225   int size, offset;
7226   sym_link *retype = getSpec (operandType (result));
7227
7228   aopOp (left, ic, FALSE);
7229
7230   /* if the operand is already in dptr
7231      then we do nothing else we move the value to dptr */
7232   if (AOP_TYPE (left) != AOP_STR)
7233     {
7234       /* if this is remateriazable */
7235       if (AOP_TYPE (left) == AOP_IMMD)
7236         {
7237           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7238           emitcode ("mov", "b,#%d", pointerCode (retype));
7239         }
7240       else
7241         {                       /* we need to get it byte by byte */
7242           emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7243           emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7244           emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7245         }
7246     }
7247   /* so dptr know contains the address */
7248   aopOp (result, ic, FALSE);
7249
7250   /* if bit then unpack */
7251   if (IS_BITVAR (retype))
7252     genUnpackBits (result, "dptr", GPOINTER);
7253   else
7254     {
7255       size = AOP_SIZE (result);
7256       offset = 0;
7257
7258       while (size--)
7259         {
7260           emitcode ("lcall", "__gptrget");
7261           aopPut (AOP (result), "a", offset++);
7262           if (size || pi)
7263             emitcode ("inc", "dptr");
7264         }
7265     }
7266
7267   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7268     aopPut ( AOP (left), "dpl", 0);
7269     aopPut ( AOP (left), "dph", 1);
7270     pi->generated = 1;
7271   }
7272   freeAsmop (left, NULL, ic, TRUE);
7273   freeAsmop (result, NULL, ic, TRUE);
7274 }
7275
7276 /*-----------------------------------------------------------------*/
7277 /* genPointerGet - generate code for pointer get                   */
7278 /*-----------------------------------------------------------------*/
7279 static void
7280 genPointerGet (iCode * ic, iCode *pi)
7281 {
7282   operand *left, *result;
7283   sym_link *type, *etype;
7284   int p_type;
7285
7286   left = IC_LEFT (ic);
7287   result = IC_RESULT (ic);
7288
7289   /* depending on the type of pointer we need to
7290      move it to the correct pointer register */
7291   type = operandType (left);
7292   etype = getSpec (type);
7293   /* if left is of type of pointer then it is simple */
7294   if (IS_PTR (type) && !IS_FUNC (type->next))
7295     p_type = DCL_TYPE (type);
7296   else
7297     {
7298       /* we have to go by the storage class */
7299       p_type = PTR_TYPE (SPEC_OCLS (etype));
7300     }
7301
7302   /* now that we have the pointer type we assign
7303      the pointer values */
7304   switch (p_type)
7305     {
7306
7307     case POINTER:
7308     case IPOINTER:
7309       genNearPointerGet (left, result, ic, pi);
7310       break;
7311
7312     case PPOINTER:
7313       genPagedPointerGet (left, result, ic, pi);
7314       break;
7315
7316     case FPOINTER:
7317       genFarPointerGet (left, result, ic, pi);
7318       break;
7319
7320     case CPOINTER:
7321       genCodePointerGet (left, result, ic, pi);
7322       break;
7323
7324     case GPOINTER:
7325       genGenPointerGet (left, result, ic, pi);
7326       break;
7327     }
7328
7329 }
7330
7331 /*-----------------------------------------------------------------*/
7332 /* genPackBits - generates code for packed bit storage             */
7333 /*-----------------------------------------------------------------*/
7334 static void
7335 genPackBits (sym_link * etype,
7336              operand * right,
7337              char *rname, int p_type)
7338 {
7339   int shCount = 0;
7340   int offset = 0;
7341   int rLen = 0;
7342   int blen, bstr;
7343   char *l;
7344
7345   blen = SPEC_BLEN (etype);
7346   bstr = SPEC_BSTR (etype);
7347
7348   l = aopGet (AOP (right), offset++, FALSE, FALSE);
7349   MOVA (l);
7350
7351   /* if the bit lenth is less than or    */
7352   /* it exactly fits a byte then         */
7353   if (SPEC_BLEN (etype) <= 8)
7354     {
7355       shCount = SPEC_BSTR (etype);
7356
7357       /* shift left acc */
7358       AccLsh (shCount);
7359
7360       if (SPEC_BLEN (etype) < 8)
7361         {                       /* if smaller than a byte */
7362
7363
7364           switch (p_type)
7365             {
7366             case POINTER:
7367               emitcode ("mov", "b,a");
7368               emitcode ("mov", "a,@%s", rname);
7369               break;
7370
7371             case FPOINTER:
7372               emitcode ("mov", "b,a");
7373               emitcode ("movx", "a,@dptr");
7374               break;
7375
7376             case GPOINTER:
7377               emitcode ("push", "b");
7378               emitcode ("push", "acc");
7379               emitcode ("lcall", "__gptrget");
7380               emitcode ("pop", "b");
7381               break;
7382             }
7383
7384           emitcode ("anl", "a,#0x%02x", (unsigned char)
7385                     ((unsigned char) (0xFF << (blen + bstr)) |
7386                      (unsigned char) (0xFF >> (8 - bstr))));
7387           emitcode ("orl", "a,b");
7388           if (p_type == GPOINTER)
7389             emitcode ("pop", "b");
7390         }
7391     }
7392
7393   switch (p_type)
7394     {
7395     case POINTER:
7396       emitcode ("mov", "@%s,a", rname);
7397       break;
7398
7399     case FPOINTER:
7400       emitcode ("movx", "@dptr,a");
7401       break;
7402
7403     case GPOINTER:
7404       emitcode ("lcall", "__gptrput");
7405       break;
7406     }
7407
7408   /* if we r done */
7409   if (SPEC_BLEN (etype) <= 8)
7410     return;
7411
7412   emitcode ("inc", "%s", rname);
7413   rLen = SPEC_BLEN (etype);
7414
7415   /* now generate for lengths greater than one byte */
7416   while (1)
7417     {
7418
7419       l = aopGet (AOP (right), offset++, FALSE, TRUE);
7420
7421       rLen -= 8;
7422       if (rLen < 8)
7423         break;
7424
7425       switch (p_type)
7426         {
7427         case POINTER:
7428           if (*l == '@')
7429             {
7430               MOVA (l);
7431               emitcode ("mov", "@%s,a", rname);
7432             }
7433           else
7434             emitcode ("mov", "@%s,%s", rname, l);
7435           break;
7436
7437         case FPOINTER:
7438           MOVA (l);
7439           emitcode ("movx", "@dptr,a");
7440           break;
7441
7442         case GPOINTER:
7443           MOVA (l);
7444           emitcode ("lcall", "__gptrput");
7445           break;
7446         }
7447       emitcode ("inc", "%s", rname);
7448     }
7449
7450   MOVA (l);
7451
7452   /* last last was not complete */
7453   if (rLen)
7454     {
7455       /* save the byte & read byte */
7456       switch (p_type)
7457         {
7458         case POINTER:
7459           emitcode ("mov", "b,a");
7460           emitcode ("mov", "a,@%s", rname);
7461           break;
7462
7463         case FPOINTER:
7464           emitcode ("mov", "b,a");
7465           emitcode ("movx", "a,@dptr");
7466           break;
7467
7468         case GPOINTER:
7469           emitcode ("push", "b");
7470           emitcode ("push", "acc");
7471           emitcode ("lcall", "__gptrget");
7472           emitcode ("pop", "b");
7473           break;
7474         }
7475
7476       emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7477       emitcode ("orl", "a,b");
7478     }
7479
7480   if (p_type == GPOINTER)
7481     emitcode ("pop", "b");
7482
7483   switch (p_type)
7484     {
7485
7486     case POINTER:
7487       emitcode ("mov", "@%s,a", rname);
7488       break;
7489
7490     case FPOINTER:
7491       emitcode ("movx", "@dptr,a");
7492       break;
7493
7494     case GPOINTER:
7495       emitcode ("lcall", "__gptrput");
7496       break;
7497     }
7498 }
7499 /*-----------------------------------------------------------------*/
7500 /* genDataPointerSet - remat pointer to data space                 */
7501 /*-----------------------------------------------------------------*/
7502 static void
7503 genDataPointerSet (operand * right,
7504                    operand * result,
7505                    iCode * ic)
7506 {
7507   int size, offset = 0;
7508   char *l, buffer[256];
7509
7510   aopOp (right, ic, FALSE);
7511
7512   l = aopGet (AOP (result), 0, FALSE, TRUE);
7513   size = AOP_SIZE (right);
7514   while (size--)
7515     {
7516       if (offset)
7517         sprintf (buffer, "(%s + %d)", l + 1, offset);
7518       else
7519         sprintf (buffer, "%s", l + 1);
7520       emitcode ("mov", "%s,%s", buffer,
7521                 aopGet (AOP (right), offset++, FALSE, FALSE));
7522     }
7523
7524   freeAsmop (right, NULL, ic, TRUE);
7525   freeAsmop (result, NULL, ic, TRUE);
7526 }
7527
7528 /*-----------------------------------------------------------------*/
7529 /* genNearPointerSet - emitcode for near pointer put                */
7530 /*-----------------------------------------------------------------*/
7531 static void
7532 genNearPointerSet (operand * right,
7533                    operand * result,
7534                    iCode * ic,
7535                    iCode * pi)
7536 {
7537   asmop *aop = NULL;
7538   regs *preg = NULL;
7539   char *rname, *l;
7540   sym_link *retype, *letype;
7541   sym_link *ptype = operandType (result);
7542
7543   retype = getSpec (operandType (right));
7544   letype = getSpec (ptype);
7545   aopOp (result, ic, FALSE);
7546
7547   /* if the result is rematerializable &
7548      in data space & not a bit variable */
7549   if (AOP_TYPE (result) == AOP_IMMD &&
7550       DCL_TYPE (ptype) == POINTER &&
7551       !IS_BITVAR (retype) &&
7552       !IS_BITVAR (letype))
7553     {
7554       genDataPointerSet (right, result, ic);
7555       return;
7556     }
7557
7558   /* if the value is already in a pointer register
7559      then don't need anything more */
7560   if (!AOP_INPREG (AOP (result)))
7561     {
7562       /* otherwise get a free pointer register */
7563       aop = newAsmop (0);
7564       preg = getFreePtr (ic, &aop, FALSE);
7565       emitcode ("mov", "%s,%s",
7566                 preg->name,
7567                 aopGet (AOP (result), 0, FALSE, TRUE));
7568       rname = preg->name;
7569     }
7570   else
7571     rname = aopGet (AOP (result), 0, FALSE, FALSE);
7572
7573   aopOp (right, ic, FALSE);
7574
7575   /* if bitfield then unpack the bits */
7576   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7577     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7578   else
7579     {
7580       /* we have can just get the values */
7581       int size = AOP_SIZE (right);
7582       int offset = 0;
7583
7584       while (size--)
7585         {
7586           l = aopGet (AOP (right), offset, FALSE, TRUE);
7587           if (*l == '@')
7588             {
7589               MOVA (l);
7590               emitcode ("mov", "@%s,a", rname);
7591             }
7592           else
7593             emitcode ("mov", "@%s,%s", rname, l);
7594           if (size || pi)
7595             emitcode ("inc", "%s", rname);
7596           offset++;
7597         }
7598     }
7599
7600   /* now some housekeeping stuff */
7601   if (aop) /* we had to allocate for this iCode */
7602     {
7603       if (pi) aopPut (AOP (result),rname,0);
7604       freeAsmop (NULL, aop, ic, TRUE);
7605     }
7606   else
7607     {
7608       /* we did not allocate which means left
7609          already in a pointer register, then
7610          if size > 0 && this could be used again
7611          we have to point it back to where it
7612          belongs */
7613       if ((AOP_SIZE (right) > 1 &&
7614            !OP_SYMBOL (result)->remat &&
7615            (OP_SYMBOL (result)->liveTo > ic->seq ||
7616             ic->depth)) &&
7617           !pi)
7618         {
7619           int size = AOP_SIZE (right) - 1;
7620           while (size--)
7621             emitcode ("dec", "%s", rname);
7622         }
7623     }
7624
7625   /* done */
7626   if (pi) pi->generated = 1;
7627   freeAsmop (result, NULL, ic, TRUE);
7628   freeAsmop (right, NULL, ic, TRUE);
7629 }
7630
7631 /*-----------------------------------------------------------------*/
7632 /* genPagedPointerSet - emitcode for Paged pointer put             */
7633 /*-----------------------------------------------------------------*/
7634 static void
7635 genPagedPointerSet (operand * right,
7636                     operand * result,
7637                     iCode * ic,
7638                     iCode * pi)
7639 {
7640   asmop *aop = NULL;
7641   regs *preg = NULL;
7642   char *rname, *l;
7643   sym_link *retype, *letype;
7644
7645   retype = getSpec (operandType (right));
7646   letype = getSpec (operandType (result));
7647
7648   aopOp (result, ic, FALSE);
7649
7650   /* if the value is already in a pointer register
7651      then don't need anything more */
7652   if (!AOP_INPREG (AOP (result)))
7653     {
7654       /* otherwise get a free pointer register */
7655       aop = newAsmop (0);
7656       preg = getFreePtr (ic, &aop, FALSE);
7657       emitcode ("mov", "%s,%s",
7658                 preg->name,
7659                 aopGet (AOP (result), 0, FALSE, TRUE));
7660       rname = preg->name;
7661     }
7662   else
7663     rname = aopGet (AOP (result), 0, FALSE, FALSE);
7664
7665   aopOp (right, ic, FALSE);
7666
7667   /* if bitfield then unpack the bits */
7668   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7669     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7670   else
7671     {
7672       /* we have can just get the values */
7673       int size = AOP_SIZE (right);
7674       int offset = 0;
7675
7676       while (size--)
7677         {
7678           l = aopGet (AOP (right), offset, FALSE, TRUE);
7679
7680           MOVA (l);
7681           emitcode ("movx", "@%s,a", rname);
7682
7683           if (size || pi)
7684             emitcode ("inc", "%s", rname);
7685
7686           offset++;
7687         }
7688     }
7689
7690   /* now some housekeeping stuff */
7691   if (aop) /* we had to allocate for this iCode */
7692     {
7693       if (pi) aopPut (AOP (result),rname,0);
7694       freeAsmop (NULL, aop, ic, TRUE);
7695     }
7696   else
7697     {
7698       /* we did not allocate which means left
7699          already in a pointer register, then
7700          if size > 0 && this could be used again
7701          we have to point it back to where it
7702          belongs */
7703       if (AOP_SIZE (right) > 1 &&
7704           !OP_SYMBOL (result)->remat &&
7705           (OP_SYMBOL (result)->liveTo > ic->seq ||
7706            ic->depth))
7707         {
7708           int size = AOP_SIZE (right) - 1;
7709           while (size--)
7710             emitcode ("dec", "%s", rname);
7711         }
7712     }
7713
7714   /* done */
7715   if (pi) pi->generated = 1;
7716   freeAsmop (result, NULL, ic, TRUE);
7717   freeAsmop (right, NULL, ic, TRUE);
7718
7719
7720 }
7721
7722 /*-----------------------------------------------------------------*/
7723 /* genFarPointerSet - set value from far space                     */
7724 /*-----------------------------------------------------------------*/
7725 static void
7726 genFarPointerSet (operand * right,
7727                   operand * result, iCode * ic, iCode * pi)
7728 {
7729   int size, offset;
7730   sym_link *retype = getSpec (operandType (right));
7731   sym_link *letype = getSpec (operandType (result));
7732   aopOp (result, ic, FALSE);
7733
7734   /* if the operand is already in dptr
7735      then we do nothing else we move the value to dptr */
7736   if (AOP_TYPE (result) != AOP_STR)
7737     {
7738       /* if this is remateriazable */
7739       if (AOP_TYPE (result) == AOP_IMMD)
7740         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7741       else
7742         {                       /* we need to get it byte by byte */
7743           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7744           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7745         }
7746     }
7747   /* so dptr know contains the address */
7748   aopOp (right, ic, FALSE);
7749
7750   /* if bit then unpack */
7751   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7752     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7753   else
7754     {
7755       size = AOP_SIZE (right);
7756       offset = 0;
7757
7758       while (size--)
7759         {
7760           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7761           MOVA (l);
7762           emitcode ("movx", "@dptr,a");
7763           if (size || pi)
7764             emitcode ("inc", "dptr");
7765         }
7766     }
7767   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7768     aopPut (AOP(result),"dpl",0);
7769     aopPut (AOP(result),"dph",1);
7770     pi->generated=1;
7771   }
7772   freeAsmop (result, NULL, ic, TRUE);
7773   freeAsmop (right, NULL, ic, TRUE);
7774 }
7775
7776 /*-----------------------------------------------------------------*/
7777 /* genGenPointerSet - set value from generic pointer space         */
7778 /*-----------------------------------------------------------------*/
7779 static void
7780 genGenPointerSet (operand * right,
7781                   operand * result, iCode * ic, iCode * pi)
7782 {
7783   int size, offset;
7784   sym_link *retype = getSpec (operandType (right));
7785   sym_link *letype = getSpec (operandType (result));
7786
7787   aopOp (result, ic, FALSE);
7788
7789   /* if the operand is already in dptr
7790      then we do nothing else we move the value to dptr */
7791   if (AOP_TYPE (result) != AOP_STR)
7792     {
7793       /* if this is remateriazable */
7794       if (AOP_TYPE (result) == AOP_IMMD)
7795         {
7796           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7797           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7798         }
7799       else
7800         {                       /* we need to get it byte by byte */
7801           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7802           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7803           emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7804         }
7805     }
7806   /* so dptr know contains the address */
7807   aopOp (right, ic, FALSE);
7808
7809   /* if bit then unpack */
7810   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7811     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7812   else
7813     {
7814       size = AOP_SIZE (right);
7815       offset = 0;
7816
7817       while (size--)
7818         {
7819           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7820           MOVA (l);
7821           emitcode ("lcall", "__gptrput");
7822           if (size || pi)
7823             emitcode ("inc", "dptr");
7824         }
7825     }
7826
7827   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7828     aopPut (AOP(result),"dpl",0);
7829     aopPut (AOP(result),"dph",1);
7830     pi->generated=1;
7831   }
7832   freeAsmop (result, NULL, ic, TRUE);
7833   freeAsmop (right, NULL, ic, TRUE);
7834 }
7835
7836 /*-----------------------------------------------------------------*/
7837 /* genPointerSet - stores the value into a pointer location        */
7838 /*-----------------------------------------------------------------*/
7839 static void
7840 genPointerSet (iCode * ic, iCode *pi)
7841 {
7842   operand *right, *result;
7843   sym_link *type, *etype;
7844   int p_type;
7845
7846   right = IC_RIGHT (ic);
7847   result = IC_RESULT (ic);
7848
7849   /* depending on the type of pointer we need to
7850      move it to the correct pointer register */
7851   type = operandType (result);
7852   etype = getSpec (type);
7853   /* if left is of type of pointer then it is simple */
7854   if (IS_PTR (type) && !IS_FUNC (type->next))
7855     {
7856       p_type = DCL_TYPE (type);
7857     }
7858   else
7859     {
7860       /* we have to go by the storage class */
7861       p_type = PTR_TYPE (SPEC_OCLS (etype));
7862     }
7863
7864   /* now that we have the pointer type we assign
7865      the pointer values */
7866   switch (p_type)
7867     {
7868
7869     case POINTER:
7870     case IPOINTER:
7871       genNearPointerSet (right, result, ic, pi);
7872       break;
7873
7874     case PPOINTER:
7875       genPagedPointerSet (right, result, ic, pi);
7876       break;
7877
7878     case FPOINTER:
7879       genFarPointerSet (right, result, ic, pi);
7880       break;
7881
7882     case GPOINTER:
7883       genGenPointerSet (right, result, ic, pi);
7884       break;
7885     }
7886
7887 }
7888
7889 /*-----------------------------------------------------------------*/
7890 /* genIfx - generate code for Ifx statement                        */
7891 /*-----------------------------------------------------------------*/
7892 static void
7893 genIfx (iCode * ic, iCode * popIc)
7894 {
7895   operand *cond = IC_COND (ic);
7896   int isbit = 0;
7897
7898   aopOp (cond, ic, FALSE);
7899
7900   /* get the value into acc */
7901   if (AOP_TYPE (cond) != AOP_CRY)
7902     toBoolean (cond);
7903   else
7904     isbit = 1;
7905   /* the result is now in the accumulator */
7906   freeAsmop (cond, NULL, ic, TRUE);
7907
7908   /* if there was something to be popped then do it */
7909   if (popIc)
7910     genIpop (popIc);
7911
7912   /* if the condition is  a bit variable */
7913   if (isbit && IS_ITEMP (cond) &&
7914       SPIL_LOC (cond))
7915     genIfxJump (ic, SPIL_LOC (cond)->rname);
7916   else if (isbit && !IS_ITEMP (cond))
7917     genIfxJump (ic, OP_SYMBOL (cond)->rname);
7918   else
7919     genIfxJump (ic, "a");
7920
7921   ic->generated = 1;
7922 }
7923
7924 /*-----------------------------------------------------------------*/
7925 /* genAddrOf - generates code for address of                       */
7926 /*-----------------------------------------------------------------*/
7927 static void
7928 genAddrOf (iCode * ic)
7929 {
7930   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7931   int size, offset;
7932
7933   aopOp (IC_RESULT (ic), ic, FALSE);
7934
7935   /* if the operand is on the stack then we
7936      need to get the stack offset of this
7937      variable */
7938   if (sym->onStack)
7939     {
7940       /* if it has an offset then we need to compute
7941          it */
7942       if (sym->stack)
7943         {
7944           emitcode ("mov", "a,_bp");
7945           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7946           aopPut (AOP (IC_RESULT (ic)), "a", 0);
7947         }
7948       else
7949         {
7950           /* we can just move _bp */
7951           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7952         }
7953       /* fill the result with zero */
7954       size = AOP_SIZE (IC_RESULT (ic)) - 1;
7955
7956       offset = 1;
7957       while (size--)
7958         {
7959           aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7960         }
7961
7962       goto release;
7963     }
7964
7965   /* object not on stack then we need the name */
7966   size = AOP_SIZE (IC_RESULT (ic));
7967   offset = 0;
7968
7969   while (size--)
7970     {
7971       char s[SDCC_NAME_MAX];
7972       if (offset)
7973         sprintf (s, "#(%s >> %d)",
7974                  sym->rname,
7975                  offset * 8);
7976       else
7977         sprintf (s, "#%s", sym->rname);
7978       aopPut (AOP (IC_RESULT (ic)), s, offset++);
7979     }
7980
7981 release:
7982   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7983
7984 }
7985
7986 /*-----------------------------------------------------------------*/
7987 /* genFarFarAssign - assignment when both are in far space         */
7988 /*-----------------------------------------------------------------*/
7989 static void
7990 genFarFarAssign (operand * result, operand * right, iCode * ic)
7991 {
7992   int size = AOP_SIZE (right);
7993   int offset = 0;
7994   char *l;
7995   /* first push the right side on to the stack */
7996   while (size--)
7997     {
7998       l = aopGet (AOP (right), offset++, FALSE, FALSE);
7999       MOVA (l);
8000       emitcode ("push", "acc");
8001     }
8002
8003   freeAsmop (right, NULL, ic, FALSE);
8004   /* now assign DPTR to result */
8005   aopOp (result, ic, FALSE);
8006   size = AOP_SIZE (result);
8007   while (size--)
8008     {
8009       emitcode ("pop", "acc");
8010       aopPut (AOP (result), "a", --offset);
8011     }
8012   freeAsmop (result, NULL, ic, FALSE);
8013
8014 }
8015
8016 /*-----------------------------------------------------------------*/
8017 /* genAssign - generate code for assignment                        */
8018 /*-----------------------------------------------------------------*/
8019 static void
8020 genAssign (iCode * ic)
8021 {
8022   operand *result, *right;
8023   int size, offset;
8024   unsigned long lit = 0L;
8025
8026   D(emitcode(";","genAssign"));
8027
8028   result = IC_RESULT (ic);
8029   right = IC_RIGHT (ic);
8030
8031   /* if they are the same */
8032   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8033     return;
8034
8035   aopOp (right, ic, FALSE);
8036
8037   /* special case both in far space */
8038   if (AOP_TYPE (right) == AOP_DPTR &&
8039       IS_TRUE_SYMOP (result) &&
8040       isOperandInFarSpace (result))
8041     {
8042
8043       genFarFarAssign (result, right, ic);
8044       return;
8045     }
8046
8047   aopOp (result, ic, TRUE);
8048
8049   /* if they are the same registers */
8050   if (sameRegs (AOP (right), AOP (result)))
8051     goto release;
8052
8053   /* if the result is a bit */
8054   if (AOP_TYPE (result) == AOP_CRY)
8055     {
8056
8057       /* if the right size is a literal then
8058          we know what the value is */
8059       if (AOP_TYPE (right) == AOP_LIT)
8060         {
8061           if (((int) operandLitValue (right)))
8062             aopPut (AOP (result), one, 0);
8063           else
8064             aopPut (AOP (result), zero, 0);
8065           goto release;
8066         }
8067
8068       /* the right is also a bit variable */
8069       if (AOP_TYPE (right) == AOP_CRY)
8070         {
8071           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8072           aopPut (AOP (result), "c", 0);
8073           goto release;
8074         }
8075
8076       /* we need to or */
8077       toBoolean (right);
8078       aopPut (AOP (result), "a", 0);
8079       goto release;
8080     }
8081
8082   /* bit variables done */
8083   /* general case */
8084   size = AOP_SIZE (result);
8085   offset = 0;
8086   if (AOP_TYPE (right) == AOP_LIT)
8087     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8088   if ((size > 1) &&
8089       (AOP_TYPE (result) != AOP_REG) &&
8090       (AOP_TYPE (right) == AOP_LIT) &&
8091       !IS_FLOAT (operandType (right)) &&
8092       (lit < 256L))
8093     {
8094       emitcode ("clr", "a");
8095       while (size--)
8096         {
8097           if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8098             aopPut (AOP (result), "a", size);
8099           else
8100             aopPut (AOP (result),
8101                     aopGet (AOP (right), size, FALSE, FALSE),
8102                     size);
8103         }
8104     }
8105   else
8106     {
8107       while (size--)
8108         {
8109           aopPut (AOP (result),
8110                   aopGet (AOP (right), offset, FALSE, FALSE),
8111                   offset);
8112           offset++;
8113         }
8114     }
8115
8116 release:
8117   freeAsmop (right, NULL, ic, TRUE);
8118   freeAsmop (result, NULL, ic, TRUE);
8119 }
8120
8121 /*-----------------------------------------------------------------*/
8122 /* genJumpTab - genrates code for jump table                       */
8123 /*-----------------------------------------------------------------*/
8124 static void
8125 genJumpTab (iCode * ic)
8126 {
8127   symbol *jtab;
8128   char *l;
8129
8130   aopOp (IC_JTCOND (ic), ic, FALSE);
8131   /* get the condition into accumulator */
8132   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8133   MOVA (l);
8134   /* multiply by three */
8135   emitcode ("add", "a,acc");
8136   emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8137   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8138
8139   jtab = newiTempLabel (NULL);
8140   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8141   emitcode ("jmp", "@a+dptr");
8142   emitcode ("", "%05d$:", jtab->key + 100);
8143   /* now generate the jump labels */
8144   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8145        jtab = setNextItem (IC_JTLABELS (ic)))
8146     emitcode ("ljmp", "%05d$", jtab->key + 100);
8147
8148 }
8149
8150 /*-----------------------------------------------------------------*/
8151 /* genCast - gen code for casting                                  */
8152 /*-----------------------------------------------------------------*/
8153 static void
8154 genCast (iCode * ic)
8155 {
8156   operand *result = IC_RESULT (ic);
8157   sym_link *ctype = operandType (IC_LEFT (ic));
8158   sym_link *rtype = operandType (IC_RIGHT (ic));
8159   operand *right = IC_RIGHT (ic);
8160   int size, offset;
8161
8162   D(emitcode(";", "genCast"));
8163
8164   /* if they are equivalent then do nothing */
8165   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8166     return;
8167
8168   aopOp (right, ic, FALSE);
8169   aopOp (result, ic, FALSE);
8170
8171   /* if the result is a bit */
8172   if (AOP_TYPE (result) == AOP_CRY)
8173     {
8174       /* if the right size is a literal then
8175          we know what the value is */
8176       if (AOP_TYPE (right) == AOP_LIT)
8177         {
8178           if (((int) operandLitValue (right)))
8179             aopPut (AOP (result), one, 0);
8180           else
8181             aopPut (AOP (result), zero, 0);
8182
8183           goto release;
8184         }
8185
8186       /* the right is also a bit variable */
8187       if (AOP_TYPE (right) == AOP_CRY)
8188         {
8189           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8190           aopPut (AOP (result), "c", 0);
8191           goto release;
8192         }
8193
8194       /* we need to or */
8195       toBoolean (right);
8196       aopPut (AOP (result), "a", 0);
8197       goto release;
8198     }
8199
8200   /* if they are the same size : or less */
8201   if (AOP_SIZE (result) <= AOP_SIZE (right))
8202     {
8203
8204       /* if they are in the same place */
8205       if (sameRegs (AOP (right), AOP (result)))
8206         goto release;
8207
8208       /* if they in different places then copy */
8209       size = AOP_SIZE (result);
8210       offset = 0;
8211       while (size--)
8212         {
8213           aopPut (AOP (result),
8214                   aopGet (AOP (right), offset, FALSE, FALSE),
8215                   offset);
8216           offset++;
8217         }
8218       goto release;
8219     }
8220
8221
8222   /* if the result is of type pointer */
8223   if (IS_PTR (ctype))
8224     {
8225
8226       int p_type;
8227       sym_link *type = operandType (right);
8228       sym_link *etype = getSpec (type);
8229
8230       /* pointer to generic pointer */
8231       if (IS_GENPTR (ctype))
8232         {
8233           char *l = zero;
8234
8235           if (IS_PTR (type))
8236             p_type = DCL_TYPE (type);
8237           else
8238             {
8239               if (SPEC_SCLS(etype)==S_REGISTER) {
8240                 // let's assume it is a generic pointer
8241                 p_type=GPOINTER;
8242               } else {
8243                 /* we have to go by the storage class */
8244                 p_type = PTR_TYPE (SPEC_OCLS (etype));
8245               }
8246             }
8247
8248           /* the first two bytes are known */
8249           size = GPTRSIZE - 1;
8250           offset = 0;
8251           while (size--)
8252             {
8253               aopPut (AOP (result),
8254                       aopGet (AOP (right), offset, FALSE, FALSE),
8255                       offset);
8256               offset++;
8257             }
8258           /* the last byte depending on type */
8259           switch (p_type)
8260             {
8261             case IPOINTER:
8262             case POINTER:
8263               l = zero;
8264               break;
8265             case FPOINTER:
8266               l = one;
8267               break;
8268             case CPOINTER:
8269               l = "#0x02";
8270               break;
8271             case GPOINTER:
8272               l = "0x03";
8273               break;
8274             case PPOINTER: // what the fck is this?
8275               l = "#0x03";
8276               break;
8277
8278             default:
8279               /* this should never happen */
8280               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8281                       "got unknown pointer type");
8282               exit (1);
8283             }
8284           aopPut (AOP (result), l, GPTRSIZE - 1);
8285           goto release;
8286         }
8287
8288       /* just copy the pointers */
8289       size = AOP_SIZE (result);
8290       offset = 0;
8291       while (size--)
8292         {
8293           aopPut (AOP (result),
8294                   aopGet (AOP (right), offset, FALSE, FALSE),
8295                   offset);
8296           offset++;
8297         }
8298       goto release;
8299     }
8300
8301   /* so we now know that the size of destination is greater
8302      than the size of the source */
8303   /* we move to result for the size of source */
8304   size = AOP_SIZE (right);
8305   offset = 0;
8306   while (size--)
8307     {
8308       aopPut (AOP (result),
8309               aopGet (AOP (right), offset, FALSE, FALSE),
8310               offset);
8311       offset++;
8312     }
8313
8314   /* now depending on the sign of the source && destination */
8315   size = AOP_SIZE (result) - AOP_SIZE (right);
8316   /* if unsigned or not an integral type */
8317   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8318     {
8319       while (size--)
8320         aopPut (AOP (result), zero, offset++);
8321     }
8322   else
8323     {
8324       /* we need to extend the sign :{ */
8325       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8326                         FALSE, FALSE);
8327       MOVA (l);
8328       emitcode ("rlc", "a");
8329       emitcode ("subb", "a,acc");
8330       while (size--)
8331         aopPut (AOP (result), "a", offset++);
8332     }
8333
8334   /* we are done hurray !!!! */
8335
8336 release:
8337   freeAsmop (right, NULL, ic, TRUE);
8338   freeAsmop (result, NULL, ic, TRUE);
8339
8340 }
8341
8342 /*-----------------------------------------------------------------*/
8343 /* genDjnz - generate decrement & jump if not zero instrucion      */
8344 /*-----------------------------------------------------------------*/
8345 static int
8346 genDjnz (iCode * ic, iCode * ifx)
8347 {
8348   symbol *lbl, *lbl1;
8349   if (!ifx)
8350     return 0;
8351
8352   /* if the if condition has a false label
8353      then we cannot save */
8354   if (IC_FALSE (ifx))
8355     return 0;
8356
8357   /* if the minus is not of the form
8358      a = a - 1 */
8359   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8360       !IS_OP_LITERAL (IC_RIGHT (ic)))
8361     return 0;
8362
8363   if (operandLitValue (IC_RIGHT (ic)) != 1)
8364     return 0;
8365
8366   /* if the size of this greater than one then no
8367      saving */
8368   if (getSize (operandType (IC_RESULT (ic))) > 1)
8369     return 0;
8370
8371   /* otherwise we can save BIG */
8372   lbl = newiTempLabel (NULL);
8373   lbl1 = newiTempLabel (NULL);
8374
8375   aopOp (IC_RESULT (ic), ic, FALSE);
8376
8377   if (AOP_NEEDSACC(IC_RESULT(ic)))
8378   {
8379       /* If the result is accessed indirectly via
8380        * the accumulator, we must explicitly write
8381        * it back after the decrement.
8382        */
8383       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8384       
8385       if (strcmp(rByte, "a"))
8386       {
8387            /* Something is hopelessly wrong */
8388            fprintf(stderr, "*** warning: internal error at %s:%d\n",
8389                    __FILE__, __LINE__);
8390            /* We can just give up; the generated code will be inefficient,
8391             * but what the hey.
8392             */
8393            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8394            return 0;
8395       }
8396       emitcode ("dec", "%s", rByte);
8397       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8398       emitcode ("jnz", "%05d$", lbl->key + 100);
8399   }
8400   else if (IS_AOP_PREG (IC_RESULT (ic)))
8401     {
8402       emitcode ("dec", "%s",
8403                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8404       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8405       emitcode ("jnz", "%05d$", lbl->key + 100);
8406     }
8407   else
8408     {
8409       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8410                 lbl->key + 100);
8411     }
8412   emitcode ("sjmp", "%05d$", lbl1->key + 100);
8413   emitcode ("", "%05d$:", lbl->key + 100);
8414   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8415   emitcode ("", "%05d$:", lbl1->key + 100);
8416
8417   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8418   ifx->generated = 1;
8419   return 1;
8420 }
8421
8422 /*-----------------------------------------------------------------*/
8423 /* genReceive - generate code for a receive iCode                  */
8424 /*-----------------------------------------------------------------*/
8425 static void
8426 genReceive (iCode * ic)
8427 {
8428   if (isOperandInFarSpace (IC_RESULT (ic)) &&
8429       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8430        IS_TRUE_SYMOP (IC_RESULT (ic))))
8431     {
8432
8433       int size = getSize (operandType (IC_RESULT (ic)));
8434       int offset = fReturnSizeMCS51 - size;
8435       while (size--)
8436         {
8437           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8438                                 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8439           offset++;
8440         }
8441       aopOp (IC_RESULT (ic), ic, FALSE);
8442       size = AOP_SIZE (IC_RESULT (ic));
8443       offset = 0;
8444       while (size--)
8445         {
8446           emitcode ("pop", "acc");
8447           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8448         }
8449
8450     }
8451   else
8452     {
8453       _G.accInUse++;
8454       aopOp (IC_RESULT (ic), ic, FALSE);
8455       _G.accInUse--;
8456       assignResultValue (IC_RESULT (ic));
8457     }
8458
8459   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8460 }
8461
8462 /*-----------------------------------------------------------------*/
8463 /* gen51Code - generate code for 8051 based controllers            */
8464 /*-----------------------------------------------------------------*/
8465 void
8466 gen51Code (iCode * lic)
8467 {
8468   iCode *ic;
8469   int cln = 0;
8470
8471   lineHead = lineCurr = NULL;
8472
8473   /* print the allocation information */
8474   if (allocInfo)
8475     printAllocInfo (currFunc, codeOutFile);
8476   /* if debug information required */
8477   /*     if (options.debug && currFunc) { */
8478   if (options.debug && currFunc)
8479     {
8480       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8481       _G.debugLine = 1;
8482       if (IS_STATIC (currFunc->etype))
8483         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8484       else
8485         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8486       _G.debugLine = 0;
8487     }
8488   /* stack pointer name */
8489   if (options.useXstack)
8490     spname = "_spx";
8491   else
8492     spname = "sp";
8493
8494
8495   for (ic = lic; ic; ic = ic->next)
8496     {
8497
8498       if (cln != ic->lineno)
8499         {
8500           if (options.debug)
8501             {
8502               _G.debugLine = 1;
8503               emitcode ("", "C$%s$%d$%d$%d ==.",
8504                         FileBaseName (ic->filename), ic->lineno,
8505                         ic->level, ic->block);
8506               _G.debugLine = 0;
8507             }
8508           emitcode (";", "%s %d", ic->filename, ic->lineno);
8509           cln = ic->lineno;
8510         }
8511       /* if the result is marked as
8512          spilt and rematerializable or code for
8513          this has already been generated then
8514          do nothing */
8515       if (resultRemat (ic) || ic->generated)
8516         continue;
8517
8518       /* depending on the operation */
8519       switch (ic->op)
8520         {
8521         case '!':
8522           genNot (ic);
8523           break;
8524
8525         case '~':
8526           genCpl (ic);
8527           break;
8528
8529         case UNARYMINUS:
8530           genUminus (ic);
8531           break;
8532
8533         case IPUSH:
8534           genIpush (ic);
8535           break;
8536
8537         case IPOP:
8538           /* IPOP happens only when trying to restore a
8539              spilt live range, if there is an ifx statement
8540              following this pop then the if statement might
8541              be using some of the registers being popped which
8542              would destory the contents of the register so
8543              we need to check for this condition and handle it */
8544           if (ic->next &&
8545               ic->next->op == IFX &&
8546               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8547             genIfx (ic->next, ic);
8548           else
8549             genIpop (ic);
8550           break;
8551
8552         case CALL:
8553           genCall (ic);
8554           break;
8555
8556         case PCALL:
8557           genPcall (ic);
8558           break;
8559
8560         case FUNCTION:
8561           genFunction (ic);
8562           break;
8563
8564         case ENDFUNCTION:
8565           genEndFunction (ic);
8566           break;
8567
8568         case RETURN:
8569           genRet (ic);
8570           break;
8571
8572         case LABEL:
8573           genLabel (ic);
8574           break;
8575
8576         case GOTO:
8577           genGoto (ic);
8578           break;
8579
8580         case '+':
8581           genPlus (ic);
8582           break;
8583
8584         case '-':
8585           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8586             genMinus (ic);
8587           break;
8588
8589         case '*':
8590           genMult (ic);
8591           break;
8592
8593         case '/':
8594           genDiv (ic);
8595           break;
8596
8597         case '%':
8598           genMod (ic);
8599           break;
8600
8601         case '>':
8602           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8603           break;
8604
8605         case '<':
8606           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8607           break;
8608
8609         case LE_OP:
8610         case GE_OP:
8611         case NE_OP:
8612
8613           /* note these two are xlated by algebraic equivalence
8614              during parsing SDCC.y */
8615           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8616                   "got '>=' or '<=' shouldn't have come here");
8617           break;
8618
8619         case EQ_OP:
8620           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8621           break;
8622
8623         case AND_OP:
8624           genAndOp (ic);
8625           break;
8626
8627         case OR_OP:
8628           genOrOp (ic);
8629           break;
8630
8631         case '^':
8632           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8633           break;
8634
8635         case '|':
8636           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8637           break;
8638
8639         case BITWISEAND:
8640           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8641           break;
8642
8643         case INLINEASM:
8644           genInline (ic);
8645           break;
8646
8647         case RRC:
8648           genRRC (ic);
8649           break;
8650
8651         case RLC:
8652           genRLC (ic);
8653           break;
8654
8655         case GETHBIT:
8656           genGetHbit (ic);
8657           break;
8658
8659         case LEFT_OP:
8660           genLeftShift (ic);
8661           break;
8662
8663         case RIGHT_OP:
8664           genRightShift (ic);
8665           break;
8666
8667         case GET_VALUE_AT_ADDRESS:
8668           genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8669           break;
8670
8671         case '=':
8672           if (POINTER_SET (ic))
8673             genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8674           else
8675             genAssign (ic);
8676           break;
8677
8678         case IFX:
8679           genIfx (ic, NULL);
8680           break;
8681
8682         case ADDRESS_OF:
8683           genAddrOf (ic);
8684           break;
8685
8686         case JUMPTABLE:
8687           genJumpTab (ic);
8688           break;
8689
8690         case CAST:
8691           genCast (ic);
8692           break;
8693
8694         case RECEIVE:
8695           genReceive (ic);
8696           break;
8697
8698         case SEND:
8699           addSet (&_G.sendSet, ic);
8700           break;
8701
8702         default:
8703           ic = ic;
8704         }
8705     }
8706
8707
8708   /* now we are ready to call the
8709      peep hole optimizer */
8710   if (!options.nopeep)
8711     peepHole (&lineHead);
8712
8713   /* now do the actual printing */
8714   printLine (lineHead, codeOutFile);
8715   return;
8716 }