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