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