partial fix for bug #444507
[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) && !defined(__MINGW32__)
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 (options.debug && 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 (options.debug && 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   if (size<1 || size>2) {
3289     // this should never happen
3290       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
3291                AOP_SIZE(result), __FILE__, lineno);
3292       exit (1);
3293   }
3294
3295   /* (if two literals: the value is computed before) */
3296   /* if one literal, literal on the right */
3297   if (AOP_TYPE (left) == AOP_LIT)
3298     {
3299       operand *t = right;
3300       right = left;
3301       left = t;
3302       //emitcode (";", "swapped left and right");
3303     }
3304
3305   if (SPEC_USIGN(opetype)
3306       // ignore the sign of left and right, what else can we do?
3307       || (SPEC_USIGN(operandType(left)) && 
3308           SPEC_USIGN(operandType(right)))) {
3309     // just an unsigned 8*8=8/16 multiply
3310     //emitcode (";","unsigned");
3311     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3312     MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3313     emitcode ("mul", "ab");
3314     aopPut (AOP (result), "a", 0);
3315     if (size==2) {
3316       aopPut (AOP (result), "b", 1);
3317     }
3318     return;
3319   }
3320
3321   // we have to do a signed multiply
3322
3323   //emitcode (";", "signed");
3324   emitcode ("clr", "F0"); // reset sign flag
3325   MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3326
3327   lbl=newiTempLabel(NULL);
3328   emitcode ("jnb", "acc.7,%05d$",  lbl->key+100);
3329   // left side is negative, 8-bit two's complement, this fails for -128
3330   emitcode ("setb", "F0"); // set sign flag
3331   emitcode ("cpl", "a");
3332   emitcode ("inc", "a");
3333
3334   emitcode ("", "%05d$:", lbl->key+100);
3335
3336   /* if literal */
3337   if (AOP_TYPE(right)==AOP_LIT) {
3338     signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3339     /* AND literal negative */
3340     if (val < 0) {
3341       emitcode ("cpl", "F0"); // complement sign flag
3342       emitcode ("mov", "b,#0x%02x", -val);
3343     } else {
3344       emitcode ("mov", "b,#0x%02x", val);
3345     }
3346   } else {
3347     lbl=newiTempLabel(NULL);
3348     emitcode ("mov", "b,a");
3349     emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3350     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3351     // right side is negative, 8-bit two's complement
3352     emitcode ("cpl", "F0"); // complement 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               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4596                 emitcode ("anl", "a,%s",
4597                           aopGet (AOP (right), offset, FALSE, FALSE));
4598               } else {
4599                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4600                 emitcode ("anl", "a,%s",
4601                           aopGet (AOP (left), offset, FALSE, FALSE));
4602               }
4603               emitcode ("jnz", "%05d$", tlbl->key + 100);
4604               offset++;
4605             }
4606           if (size)
4607             {
4608               CLRC;
4609               emitcode ("", "%05d$:", tlbl->key + 100);
4610               outBitC (result);
4611             }
4612           else if (ifx)
4613             jmpTrueOrFalse (ifx, tlbl);
4614         }
4615       else
4616         {
4617           for (; (size--); offset++)
4618             {
4619               // normal case
4620               // result = left & right
4621               if (AOP_TYPE (right) == AOP_LIT)
4622                 {
4623                   if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4624                     {
4625                       aopPut (AOP (result),
4626                               aopGet (AOP (left), offset, FALSE, FALSE),
4627                               offset);
4628                       continue;
4629                     }
4630                   else if (bytelit == 0)
4631                     {
4632                       aopPut (AOP (result), zero, offset);
4633                       continue;
4634                     }
4635                 }
4636               // faster than result <- left, anl result,right
4637               // and better if result is SFR
4638               if (AOP_TYPE (left) == AOP_ACC)
4639                 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4640               else
4641                 {
4642                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4643                   emitcode ("anl", "a,%s",
4644                             aopGet (AOP (left), offset, FALSE, FALSE));
4645                 }
4646               aopPut (AOP (result), "a", offset);
4647             }
4648         }
4649     }
4650
4651 release:
4652   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4653   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4654   freeAsmop (result, NULL, ic, TRUE);
4655 }
4656
4657 /*-----------------------------------------------------------------*/
4658 /* genOr  - code for or                                            */
4659 /*-----------------------------------------------------------------*/
4660 static void
4661 genOr (iCode * ic, iCode * ifx)
4662 {
4663   operand *left, *right, *result;
4664   int size, offset = 0;
4665   unsigned long lit = 0L;
4666
4667   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4668   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4669   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4670
4671 #ifdef DEBUG_TYPE
4672   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4673             AOP_TYPE (result),
4674             AOP_TYPE (left), AOP_TYPE (right));
4675   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4676             AOP_SIZE (result),
4677             AOP_SIZE (left), AOP_SIZE (right));
4678 #endif
4679
4680   /* if left is a literal & right is not then exchange them */
4681   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4682       AOP_NEEDSACC (left))
4683     {
4684       operand *tmp = right;
4685       right = left;
4686       left = tmp;
4687     }
4688
4689   /* if result = right then exchange them */
4690   if (sameRegs (AOP (result), AOP (right)))
4691     {
4692       operand *tmp = right;
4693       right = left;
4694       left = tmp;
4695     }
4696
4697   /* if right is bit then exchange them */
4698   if (AOP_TYPE (right) == AOP_CRY &&
4699       AOP_TYPE (left) != AOP_CRY)
4700     {
4701       operand *tmp = right;
4702       right = left;
4703       left = tmp;
4704     }
4705   if (AOP_TYPE (right) == AOP_LIT)
4706     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4707
4708   size = AOP_SIZE (result);
4709
4710   // if(bit | yy)
4711   // xx = bit | yy;
4712   if (AOP_TYPE (left) == AOP_CRY)
4713     {
4714       if (AOP_TYPE (right) == AOP_LIT)
4715         {
4716           // c = bit & literal;
4717           if (lit)
4718             {
4719               // lit != 0 => result = 1
4720               if (AOP_TYPE (result) == AOP_CRY)
4721                 {
4722                   if (size)
4723                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4724                   else if (ifx)
4725                     continueIfTrue (ifx);
4726                   goto release;
4727                 }
4728               emitcode ("setb", "c");
4729             }
4730           else
4731             {
4732               // lit == 0 => result = left
4733               if (size && sameRegs (AOP (result), AOP (left)))
4734                 goto release;
4735               emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4736             }
4737         }
4738       else
4739         {
4740           if (AOP_TYPE (right) == AOP_CRY)
4741             {
4742               // c = bit | bit;
4743               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4744               emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4745             }
4746           else
4747             {
4748               // c = bit | val;
4749               symbol *tlbl = newiTempLabel (NULL);
4750               if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4751                 emitcode ("setb", "c");
4752               emitcode ("jb", "%s,%05d$",
4753                         AOP (left)->aopu.aop_dir, tlbl->key + 100);
4754               toBoolean (right);
4755               emitcode ("jnz", "%05d$", tlbl->key + 100);
4756               if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4757                 {
4758                   jmpTrueOrFalse (ifx, tlbl);
4759                   goto release;
4760                 }
4761               else
4762                 {
4763                   CLRC;
4764                   emitcode ("", "%05d$:", tlbl->key + 100);
4765                 }
4766             }
4767         }
4768       // bit = c
4769       // val = c
4770       if (size)
4771         outBitC (result);
4772       // if(bit | ...)
4773       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4774         genIfxJump (ifx, "c");
4775       goto release;
4776     }
4777
4778   // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
4779   // bit = val | 0xZZ     - size = 1, ifx = FALSE -
4780   if ((AOP_TYPE (right) == AOP_LIT) &&
4781       (AOP_TYPE (result) == AOP_CRY) &&
4782       (AOP_TYPE (left) != AOP_CRY))
4783     {
4784       if (lit)
4785         {
4786           // result = 1
4787           if (size)
4788             emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4789           else
4790             continueIfTrue (ifx);
4791           goto release;
4792         }
4793       else
4794         {
4795           // lit = 0, result = boolean(left)
4796           if (size)
4797             emitcode ("setb", "c");
4798           toBoolean (right);
4799           if (size)
4800             {
4801               symbol *tlbl = newiTempLabel (NULL);
4802               emitcode ("jnz", "%05d$", tlbl->key + 100);
4803               CLRC;
4804               emitcode ("", "%05d$:", tlbl->key + 100);
4805             }
4806           else
4807             {
4808               genIfxJump (ifx, "a");
4809               goto release;
4810             }
4811         }
4812       outBitC (result);
4813       goto release;
4814     }
4815
4816   /* if left is same as result */
4817   if (sameRegs (AOP (result), AOP (left)))
4818     {
4819       for (; size--; offset++)
4820         {
4821           if (AOP_TYPE (right) == AOP_LIT)
4822             {
4823               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4824                 continue;
4825               else if (IS_AOP_PREG (left))
4826                 {
4827                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4828                   emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4829                   aopPut (AOP (result), "a", offset);
4830                 }
4831               else
4832                 emitcode ("orl", "%s,%s",
4833                           aopGet (AOP (left), offset, FALSE, TRUE),
4834                           aopGet (AOP (right), offset, FALSE, FALSE));
4835             }
4836           else
4837             {
4838               if (AOP_TYPE (left) == AOP_ACC)
4839                 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4840               else
4841                 {
4842                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4843                   if (IS_AOP_PREG (left))
4844                     {
4845                       emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4846                       aopPut (AOP (result), "a", offset);
4847                     }
4848                   else
4849                     emitcode ("orl", "%s,a",
4850                               aopGet (AOP (left), offset, FALSE, TRUE));
4851                 }
4852             }
4853         }
4854     }
4855   else
4856     {
4857       // left & result in different registers
4858       if (AOP_TYPE (result) == AOP_CRY)
4859         {
4860           // result = bit
4861           // if(size), result in bit
4862           // if(!size && ifx), conditional oper: if(left | right)
4863           symbol *tlbl = newiTempLabel (NULL);
4864           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4865           if (size)
4866             emitcode ("setb", "c");
4867           while (sizer--)
4868             {
4869               if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4870                 emitcode ("orl", "a,%s",
4871                           aopGet (AOP (right), offset, FALSE, FALSE));
4872               } else {
4873                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4874                 emitcode ("orl", "a,%s",
4875                           aopGet (AOP (left), offset, FALSE, FALSE));
4876               }
4877               emitcode ("jnz", "%05d$", tlbl->key + 100);
4878               offset++;
4879             }
4880           if (size)
4881             {
4882               CLRC;
4883               emitcode ("", "%05d$:", tlbl->key + 100);
4884               outBitC (result);
4885             }
4886           else if (ifx)
4887             jmpTrueOrFalse (ifx, tlbl);
4888         }
4889       else
4890         for (; (size--); offset++)
4891           {
4892             // normal case
4893             // result = left & right
4894             if (AOP_TYPE (right) == AOP_LIT)
4895               {
4896                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4897                   {
4898                     aopPut (AOP (result),
4899                             aopGet (AOP (left), offset, FALSE, FALSE),
4900                             offset);
4901                     continue;
4902                   }
4903               }
4904             // faster than result <- left, anl result,right
4905             // and better if result is SFR
4906             if (AOP_TYPE (left) == AOP_ACC)
4907               emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4908             else
4909               {
4910                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4911                 emitcode ("orl", "a,%s",
4912                           aopGet (AOP (left), offset, FALSE, FALSE));
4913               }
4914             aopPut (AOP (result), "a", offset);
4915           }
4916     }
4917
4918 release:
4919   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4920   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4921   freeAsmop (result, NULL, ic, TRUE);
4922 }
4923
4924 /*-----------------------------------------------------------------*/
4925 /* genXor - code for xclusive or                                   */
4926 /*-----------------------------------------------------------------*/
4927 static void
4928 genXor (iCode * ic, iCode * ifx)
4929 {
4930   operand *left, *right, *result;
4931   int size, offset = 0;
4932   unsigned long lit = 0L;
4933
4934   aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4935   aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4936   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4937
4938 #ifdef DEBUG_TYPE
4939   emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4940             AOP_TYPE (result),
4941             AOP_TYPE (left), AOP_TYPE (right));
4942   emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4943             AOP_SIZE (result),
4944             AOP_SIZE (left), AOP_SIZE (right));
4945 #endif
4946
4947   /* if left is a literal & right is not ||
4948      if left needs acc & right does not */
4949   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4950       (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
4951     {
4952       operand *tmp = right;
4953       right = left;
4954       left = tmp;
4955     }
4956
4957   /* if result = right then exchange them */
4958   if (sameRegs (AOP (result), AOP (right)))
4959     {
4960       operand *tmp = right;
4961       right = left;
4962       left = tmp;
4963     }
4964
4965   /* if right is bit then exchange them */
4966   if (AOP_TYPE (right) == AOP_CRY &&
4967       AOP_TYPE (left) != AOP_CRY)
4968     {
4969       operand *tmp = right;
4970       right = left;
4971       left = tmp;
4972     }
4973   if (AOP_TYPE (right) == AOP_LIT)
4974     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4975
4976   size = AOP_SIZE (result);
4977
4978   // if(bit ^ yy)
4979   // xx = bit ^ yy;
4980   if (AOP_TYPE (left) == AOP_CRY)
4981     {
4982       if (AOP_TYPE (right) == AOP_LIT)
4983         {
4984           // c = bit & literal;
4985           if (lit >> 1)
4986             {
4987               // lit>>1  != 0 => result = 1
4988               if (AOP_TYPE (result) == AOP_CRY)
4989                 {
4990                   if (size)
4991                     emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4992                   else if (ifx)
4993                     continueIfTrue (ifx);
4994                   goto release;
4995                 }
4996               emitcode ("setb", "c");
4997             }
4998           else
4999             {
5000               // lit == (0 or 1)
5001               if (lit == 0)
5002                 {
5003                   // lit == 0, result = left
5004                   if (size && sameRegs (AOP (result), AOP (left)))
5005                     goto release;
5006                   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5007                 }
5008               else
5009                 {
5010                   // lit == 1, result = not(left)
5011                   if (size && sameRegs (AOP (result), AOP (left)))
5012                     {
5013                       emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5014                       goto release;
5015                     }
5016                   else
5017                     {
5018                       emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5019                       emitcode ("cpl", "c");
5020                     }
5021                 }
5022             }
5023
5024         }
5025       else
5026         {
5027           // right != literal
5028           symbol *tlbl = newiTempLabel (NULL);
5029           if (AOP_TYPE (right) == AOP_CRY)
5030             {
5031               // c = bit ^ bit;
5032               emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5033             }
5034           else
5035             {
5036               int sizer = AOP_SIZE (right);
5037               // c = bit ^ val
5038               // if val>>1 != 0, result = 1
5039               emitcode ("setb", "c");
5040               while (sizer)
5041                 {
5042                   MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5043                   if (sizer == 1)
5044                     // test the msb of the lsb
5045                     emitcode ("anl", "a,#0xfe");
5046                   emitcode ("jnz", "%05d$", tlbl->key + 100);
5047                   sizer--;
5048                 }
5049               // val = (0,1)
5050               emitcode ("rrc", "a");
5051             }
5052           emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5053           emitcode ("cpl", "c");
5054           emitcode ("", "%05d$:", (tlbl->key + 100));
5055         }
5056       // bit = c
5057       // val = c
5058       if (size)
5059         outBitC (result);
5060       // if(bit | ...)
5061       else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5062         genIfxJump (ifx, "c");
5063       goto release;
5064     }
5065
5066   if (sameRegs (AOP (result), AOP (left)))
5067     {
5068       /* if left is same as result */
5069       for (; size--; offset++)
5070         {
5071           if (AOP_TYPE (right) == AOP_LIT)
5072             {
5073               if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5074                 continue;
5075               else if (IS_AOP_PREG (left))
5076                 {
5077                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5078                   emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5079                   aopPut (AOP (result), "a", offset);
5080                 }
5081               else
5082                 emitcode ("xrl", "%s,%s",
5083                           aopGet (AOP (left), offset, FALSE, TRUE),
5084                           aopGet (AOP (right), offset, FALSE, FALSE));
5085             }
5086           else
5087             {
5088               if (AOP_TYPE (left) == AOP_ACC)
5089                 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5090               else
5091                 {
5092                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5093                   if (IS_AOP_PREG (left))
5094                     {
5095                       emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5096                       aopPut (AOP (result), "a", offset);
5097                     }
5098                   else
5099                     emitcode ("xrl", "%s,a",
5100                               aopGet (AOP (left), offset, FALSE, TRUE));
5101                 }
5102             }
5103         }
5104     }
5105   else
5106     {
5107       // left & result in different registers
5108       if (AOP_TYPE (result) == AOP_CRY)
5109         {
5110           // result = bit
5111           // if(size), result in bit
5112           // if(!size && ifx), conditional oper: if(left ^ right)
5113           symbol *tlbl = newiTempLabel (NULL);
5114           int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5115           if (size)
5116             emitcode ("setb", "c");
5117           while (sizer--)
5118             {
5119               if ((AOP_TYPE (right) == AOP_LIT) &&
5120                   (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5121                 {
5122                   MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5123                 }
5124               else
5125                 {
5126                   if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5127                     emitcode ("xrl", "a,%s",
5128                               aopGet (AOP (right), offset, FALSE, FALSE));
5129                   } else {
5130                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5131                     emitcode ("xrl", "a,%s",
5132                               aopGet (AOP (left), offset, FALSE, FALSE));
5133                   }
5134                 }
5135               emitcode ("jnz", "%05d$", tlbl->key + 100);
5136               offset++;
5137             }
5138           if (size)
5139             {
5140               CLRC;
5141               emitcode ("", "%05d$:", tlbl->key + 100);
5142               outBitC (result);
5143             }
5144           else if (ifx)
5145             jmpTrueOrFalse (ifx, tlbl);
5146         }
5147       else
5148         for (; (size--); offset++)
5149           {
5150             // normal case
5151             // result = left & right
5152             if (AOP_TYPE (right) == AOP_LIT)
5153               {
5154                 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5155                   {
5156                     aopPut (AOP (result),
5157                             aopGet (AOP (left), offset, FALSE, FALSE),
5158                             offset);
5159                     continue;
5160                   }
5161               }
5162             // faster than result <- left, anl result,right
5163             // and better if result is SFR
5164             if (AOP_TYPE (left) == AOP_ACC)
5165               emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5166             else
5167               {
5168                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5169                 emitcode ("xrl", "a,%s",
5170                           aopGet (AOP (left), offset, FALSE, TRUE));
5171               }
5172             aopPut (AOP (result), "a", offset);
5173           }
5174     }
5175
5176 release:
5177   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5178   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5179   freeAsmop (result, NULL, ic, TRUE);
5180 }
5181
5182 /*-----------------------------------------------------------------*/
5183 /* genInline - write the inline code out                           */
5184 /*-----------------------------------------------------------------*/
5185 static void
5186 genInline (iCode * ic)
5187 {
5188   char *buffer, *bp, *bp1;
5189
5190   _G.inLine += (!options.asmpeep);
5191
5192   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5193   strcpy (buffer, IC_INLINE (ic));
5194
5195   /* emit each line as a code */
5196   while (*bp)
5197     {
5198       if (*bp == '\n')
5199         {
5200           *bp++ = '\0';
5201           emitcode (bp1, "");
5202           bp1 = bp;
5203         }
5204       else
5205         {
5206           if (*bp == ':')
5207             {
5208               bp++;
5209               *bp = '\0';
5210               bp++;
5211               emitcode (bp1, "");
5212               bp1 = bp;
5213             }
5214           else
5215             bp++;
5216         }
5217     }
5218   if (bp1 != bp)
5219     emitcode (bp1, "");
5220   /*     emitcode("",buffer); */
5221   _G.inLine -= (!options.asmpeep);
5222 }
5223
5224 /*-----------------------------------------------------------------*/
5225 /* genRRC - rotate right with carry                                */
5226 /*-----------------------------------------------------------------*/
5227 static void
5228 genRRC (iCode * ic)
5229 {
5230   operand *left, *result;
5231   int size, offset = 0;
5232   char *l;
5233
5234   /* rotate right with carry */
5235   left = IC_LEFT (ic);
5236   result = IC_RESULT (ic);
5237   aopOp (left, ic, FALSE);
5238   aopOp (result, ic, FALSE);
5239
5240   /* move it to the result */
5241   size = AOP_SIZE (result);
5242   offset = size - 1;
5243   CLRC;
5244   while (size--)
5245     {
5246       l = aopGet (AOP (left), offset, FALSE, FALSE);
5247       MOVA (l);
5248       emitcode ("rrc", "a");
5249       if (AOP_SIZE (result) > 1)
5250         aopPut (AOP (result), "a", offset--);
5251     }
5252   /* now we need to put the carry into the
5253      highest order byte of the result */
5254   if (AOP_SIZE (result) > 1)
5255     {
5256       l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5257       MOVA (l);
5258     }
5259   emitcode ("mov", "acc.7,c");
5260   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5261   freeAsmop (left, NULL, ic, TRUE);
5262   freeAsmop (result, NULL, ic, TRUE);
5263 }
5264
5265 /*-----------------------------------------------------------------*/
5266 /* genRLC - generate code for rotate left with carry               */
5267 /*-----------------------------------------------------------------*/
5268 static void
5269 genRLC (iCode * ic)
5270 {
5271   operand *left, *result;
5272   int size, offset = 0;
5273   char *l;
5274
5275   /* rotate right with carry */
5276   left = IC_LEFT (ic);
5277   result = IC_RESULT (ic);
5278   aopOp (left, ic, FALSE);
5279   aopOp (result, ic, FALSE);
5280
5281   /* move it to the result */
5282   size = AOP_SIZE (result);
5283   offset = 0;
5284   if (size--)
5285     {
5286       l = aopGet (AOP (left), offset, FALSE, FALSE);
5287       MOVA (l);
5288       emitcode ("add", "a,acc");
5289       if (AOP_SIZE (result) > 1)
5290         aopPut (AOP (result), "a", offset++);
5291       while (size--)
5292         {
5293           l = aopGet (AOP (left), offset, FALSE, FALSE);
5294           MOVA (l);
5295           emitcode ("rlc", "a");
5296           if (AOP_SIZE (result) > 1)
5297             aopPut (AOP (result), "a", offset++);
5298         }
5299     }
5300   /* now we need to put the carry into the
5301      highest order byte of the result */
5302   if (AOP_SIZE (result) > 1)
5303     {
5304       l = aopGet (AOP (result), 0, FALSE, FALSE);
5305       MOVA (l);
5306     }
5307   emitcode ("mov", "acc.0,c");
5308   aopPut (AOP (result), "a", 0);
5309   freeAsmop (left, NULL, ic, TRUE);
5310   freeAsmop (result, NULL, ic, TRUE);
5311 }
5312
5313 /*-----------------------------------------------------------------*/
5314 /* genGetHbit - generates code get highest order bit               */
5315 /*-----------------------------------------------------------------*/
5316 static void
5317 genGetHbit (iCode * ic)
5318 {
5319   operand *left, *result;
5320   left = IC_LEFT (ic);
5321   result = IC_RESULT (ic);
5322   aopOp (left, ic, FALSE);
5323   aopOp (result, ic, FALSE);
5324
5325   /* get the highest order byte into a */
5326   MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5327   if (AOP_TYPE (result) == AOP_CRY)
5328     {
5329       emitcode ("rlc", "a");
5330       outBitC (result);
5331     }
5332   else
5333     {
5334       emitcode ("rl", "a");
5335       emitcode ("anl", "a,#0x01");
5336       outAcc (result);
5337     }
5338
5339
5340   freeAsmop (left, NULL, ic, TRUE);
5341   freeAsmop (result, NULL, ic, TRUE);
5342 }
5343
5344 /*-----------------------------------------------------------------*/
5345 /* AccRol - rotate left accumulator by known count                 */
5346 /*-----------------------------------------------------------------*/
5347 static void
5348 AccRol (int shCount)
5349 {
5350   shCount &= 0x0007;            // shCount : 0..7
5351
5352   switch (shCount)
5353     {
5354     case 0:
5355       break;
5356     case 1:
5357       emitcode ("rl", "a");
5358       break;
5359     case 2:
5360       emitcode ("rl", "a");
5361       emitcode ("rl", "a");
5362       break;
5363     case 3:
5364       emitcode ("swap", "a");
5365       emitcode ("rr", "a");
5366       break;
5367     case 4:
5368       emitcode ("swap", "a");
5369       break;
5370     case 5:
5371       emitcode ("swap", "a");
5372       emitcode ("rl", "a");
5373       break;
5374     case 6:
5375       emitcode ("rr", "a");
5376       emitcode ("rr", "a");
5377       break;
5378     case 7:
5379       emitcode ("rr", "a");
5380       break;
5381     }
5382 }
5383
5384 /*-----------------------------------------------------------------*/
5385 /* AccLsh - left shift accumulator by known count                  */
5386 /*-----------------------------------------------------------------*/
5387 static void
5388 AccLsh (int shCount)
5389 {
5390   if (shCount != 0)
5391     {
5392       if (shCount == 1)
5393         emitcode ("add", "a,acc");
5394       else if (shCount == 2)
5395         {
5396           emitcode ("add", "a,acc");
5397           emitcode ("add", "a,acc");
5398         }
5399       else
5400         {
5401           /* rotate left accumulator */
5402           AccRol (shCount);
5403           /* and kill the lower order bits */
5404           emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5405         }
5406     }
5407 }
5408
5409 /*-----------------------------------------------------------------*/
5410 /* AccRsh - right shift accumulator by known count                 */
5411 /*-----------------------------------------------------------------*/
5412 static void
5413 AccRsh (int shCount)
5414 {
5415   if (shCount != 0)
5416     {
5417       if (shCount == 1)
5418         {
5419           CLRC;
5420           emitcode ("rrc", "a");
5421         }
5422       else
5423         {
5424           /* rotate right accumulator */
5425           AccRol (8 - shCount);
5426           /* and kill the higher order bits */
5427           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5428         }
5429     }
5430 }
5431
5432 /*-----------------------------------------------------------------*/
5433 /* AccSRsh - signed right shift accumulator by known count                 */
5434 /*-----------------------------------------------------------------*/
5435 static void
5436 AccSRsh (int shCount)
5437 {
5438   symbol *tlbl;
5439   if (shCount != 0)
5440     {
5441       if (shCount == 1)
5442         {
5443           emitcode ("mov", "c,acc.7");
5444           emitcode ("rrc", "a");
5445         }
5446       else if (shCount == 2)
5447         {
5448           emitcode ("mov", "c,acc.7");
5449           emitcode ("rrc", "a");
5450           emitcode ("mov", "c,acc.7");
5451           emitcode ("rrc", "a");
5452         }
5453       else
5454         {
5455           tlbl = newiTempLabel (NULL);
5456           /* rotate right accumulator */
5457           AccRol (8 - shCount);
5458           /* and kill the higher order bits */
5459           emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5460           emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5461           emitcode ("orl", "a,#0x%02x",
5462                     (unsigned char) ~SRMask[shCount]);
5463           emitcode ("", "%05d$:", tlbl->key + 100);
5464         }
5465     }
5466 }
5467
5468 /*-----------------------------------------------------------------*/
5469 /* shiftR1Left2Result - shift right one byte from left to result   */
5470 /*-----------------------------------------------------------------*/
5471 static void
5472 shiftR1Left2Result (operand * left, int offl,
5473                     operand * result, int offr,
5474                     int shCount, int sign)
5475 {
5476   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5477   /* shift right accumulator */
5478   if (sign)
5479     AccSRsh (shCount);
5480   else
5481     AccRsh (shCount);
5482   aopPut (AOP (result), "a", offr);
5483 }
5484
5485 /*-----------------------------------------------------------------*/
5486 /* shiftL1Left2Result - shift left one byte from left to result    */
5487 /*-----------------------------------------------------------------*/
5488 static void
5489 shiftL1Left2Result (operand * left, int offl,
5490                     operand * result, int offr, int shCount)
5491 {
5492   char *l;
5493   l = aopGet (AOP (left), offl, FALSE, FALSE);
5494   MOVA (l);
5495   /* shift left accumulator */
5496   AccLsh (shCount);
5497   aopPut (AOP (result), "a", offr);
5498 }
5499
5500 /*-----------------------------------------------------------------*/
5501 /* movLeft2Result - move byte from left to result                  */
5502 /*-----------------------------------------------------------------*/
5503 static void
5504 movLeft2Result (operand * left, int offl,
5505                 operand * result, int offr, int sign)
5506 {
5507   char *l;
5508   if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5509     {
5510       l = aopGet (AOP (left), offl, FALSE, FALSE);
5511
5512       if (*l == '@' && (IS_AOP_PREG (result)))
5513         {
5514           emitcode ("mov", "a,%s", l);
5515           aopPut (AOP (result), "a", offr);
5516         }
5517       else
5518         {
5519           if (!sign)
5520             aopPut (AOP (result), l, offr);
5521           else
5522             {
5523               /* MSB sign in acc.7 ! */
5524               if (getDataSize (left) == offl + 1)
5525                 {
5526                   emitcode ("mov", "a,%s", l);
5527                   aopPut (AOP (result), "a", offr);
5528                 }
5529             }
5530         }
5531     }
5532 }
5533
5534 /*-----------------------------------------------------------------*/
5535 /* AccAXRrl1 - right rotate c->a:x->c by 1                         */
5536 /*-----------------------------------------------------------------*/
5537 static void
5538 AccAXRrl1 (char *x)
5539 {
5540   emitcode ("rrc", "a");
5541   emitcode ("xch", "a,%s", x);
5542   emitcode ("rrc", "a");
5543   emitcode ("xch", "a,%s", x);
5544 }
5545
5546 /*-----------------------------------------------------------------*/
5547 /* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
5548 /*-----------------------------------------------------------------*/
5549 static void
5550 AccAXLrl1 (char *x)
5551 {
5552   emitcode ("xch", "a,%s", x);
5553   emitcode ("rlc", "a");
5554   emitcode ("xch", "a,%s", x);
5555   emitcode ("rlc", "a");
5556 }
5557
5558 /*-----------------------------------------------------------------*/
5559 /* AccAXLsh1 - left shift a:x<-0 by 1                              */
5560 /*-----------------------------------------------------------------*/
5561 static void
5562 AccAXLsh1 (char *x)
5563 {
5564   emitcode ("xch", "a,%s", x);
5565   emitcode ("add", "a,acc");
5566   emitcode ("xch", "a,%s", x);
5567   emitcode ("rlc", "a");
5568 }
5569
5570 /*-----------------------------------------------------------------*/
5571 /* AccAXLsh - left shift a:x by known count (0..7)                 */
5572 /*-----------------------------------------------------------------*/
5573 static void
5574 AccAXLsh (char *x, int shCount)
5575 {
5576   switch (shCount)
5577     {
5578     case 0:
5579       break;
5580     case 1:
5581       AccAXLsh1 (x);
5582       break;
5583     case 2:
5584       AccAXLsh1 (x);
5585       AccAXLsh1 (x);
5586       break;
5587     case 3:
5588     case 4:
5589     case 5:                     // AAAAABBB:CCCCCDDD
5590
5591       AccRol (shCount);         // BBBAAAAA:CCCCCDDD
5592
5593       emitcode ("anl", "a,#0x%02x",
5594                 SLMask[shCount]);       // BBB00000:CCCCCDDD
5595
5596       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBB00000
5597
5598       AccRol (shCount);         // DDDCCCCC:BBB00000
5599
5600       emitcode ("xch", "a,%s", x);      // BBB00000:DDDCCCCC
5601
5602       emitcode ("xrl", "a,%s", x);      // (BBB^DDD)CCCCC:DDDCCCCC
5603
5604       emitcode ("xch", "a,%s", x);      // DDDCCCCC:(BBB^DDD)CCCCC
5605
5606       emitcode ("anl", "a,#0x%02x",
5607                 SLMask[shCount]);       // DDD00000:(BBB^DDD)CCCCC
5608
5609       emitcode ("xch", "a,%s", x);      // (BBB^DDD)CCCCC:DDD00000
5610
5611       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:DDD00000
5612
5613       break;
5614     case 6:                     // AAAAAABB:CCCCCCDD
5615       emitcode ("anl", "a,#0x%02x",
5616                 SRMask[shCount]);       // 000000BB:CCCCCCDD
5617       emitcode ("mov", "c,acc.0");      // c = B
5618       emitcode ("xch", "a,%s", x);      // CCCCCCDD:000000BB
5619 #if 0 // REMOVE ME
5620       AccAXRrl1 (x);            // BCCCCCCD:D000000B
5621       AccAXRrl1 (x);            // BBCCCCCC:DD000000
5622 #else
5623       emitcode("rrc","a"); 
5624       emitcode("xch","a,%s", x); 
5625       emitcode("rrc","a"); 
5626       emitcode("mov","c,acc.0"); //<< get correct bit 
5627       emitcode("xch","a,%s", x); 
5628
5629       emitcode("rrc","a"); 
5630       emitcode("xch","a,%s", x); 
5631       emitcode("rrc","a"); 
5632       emitcode("xch","a,%s", x); 
5633 #endif
5634       break;
5635     case 7:                     // a:x <<= 7
5636
5637       emitcode ("anl", "a,#0x%02x",
5638                 SRMask[shCount]);       // 0000000B:CCCCCCCD
5639
5640       emitcode ("mov", "c,acc.0");      // c = B
5641
5642       emitcode ("xch", "a,%s", x);      // CCCCCCCD:0000000B
5643
5644       AccAXRrl1 (x);            // BCCCCCCC:D0000000
5645
5646       break;
5647     default:
5648       break;
5649     }
5650 }
5651
5652 /*-----------------------------------------------------------------*/
5653 /* AccAXRsh - right shift a:x known count (0..7)                   */
5654 /*-----------------------------------------------------------------*/
5655 static void
5656 AccAXRsh (char *x, int shCount)
5657 {
5658   switch (shCount)
5659     {
5660     case 0:
5661       break;
5662     case 1:
5663       CLRC;
5664       AccAXRrl1 (x);            // 0->a:x
5665
5666       break;
5667     case 2:
5668       CLRC;
5669       AccAXRrl1 (x);            // 0->a:x
5670
5671       CLRC;
5672       AccAXRrl1 (x);            // 0->a:x
5673
5674       break;
5675     case 3:
5676     case 4:
5677     case 5:                     // AAAAABBB:CCCCCDDD = a:x
5678
5679       AccRol (8 - shCount);     // BBBAAAAA:DDDCCCCC
5680
5681       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
5682
5683       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
5684
5685       emitcode ("anl", "a,#0x%02x",
5686                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
5687
5688       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
5689
5690       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
5691
5692       emitcode ("anl", "a,#0x%02x",
5693                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
5694
5695       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
5696
5697       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
5698
5699       emitcode ("xch", "a,%s", x);      // 000AAAAA:BBBCCCCC
5700
5701       break;
5702     case 6:                     // AABBBBBB:CCDDDDDD
5703
5704       emitcode ("mov", "c,acc.7");
5705       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
5706
5707       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
5708
5709       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
5710
5711       emitcode ("anl", "a,#0x%02x",
5712                 SRMask[shCount]);       // 000000AA:BBBBBBCC
5713
5714       break;
5715     case 7:                     // ABBBBBBB:CDDDDDDD
5716
5717       emitcode ("mov", "c,acc.7");      // c = A
5718
5719       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
5720
5721       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
5722
5723       emitcode ("anl", "a,#0x%02x",
5724                 SRMask[shCount]);       // 0000000A:BBBBBBBC
5725
5726       break;
5727     default:
5728       break;
5729     }
5730 }
5731
5732 /*-----------------------------------------------------------------*/
5733 /* AccAXRshS - right shift signed a:x known count (0..7)           */
5734 /*-----------------------------------------------------------------*/
5735 static void
5736 AccAXRshS (char *x, int shCount)
5737 {
5738   symbol *tlbl;
5739   switch (shCount)
5740     {
5741     case 0:
5742       break;
5743     case 1:
5744       emitcode ("mov", "c,acc.7");
5745       AccAXRrl1 (x);            // s->a:x
5746
5747       break;
5748     case 2:
5749       emitcode ("mov", "c,acc.7");
5750       AccAXRrl1 (x);            // s->a:x
5751
5752       emitcode ("mov", "c,acc.7");
5753       AccAXRrl1 (x);            // s->a:x
5754
5755       break;
5756     case 3:
5757     case 4:
5758     case 5:                     // AAAAABBB:CCCCCDDD = a:x
5759
5760       tlbl = newiTempLabel (NULL);
5761       AccRol (8 - shCount);     // BBBAAAAA:CCCCCDDD
5762
5763       emitcode ("xch", "a,%s", x);      // CCCCCDDD:BBBAAAAA
5764
5765       AccRol (8 - shCount);     // DDDCCCCC:BBBAAAAA
5766
5767       emitcode ("anl", "a,#0x%02x",
5768                 SRMask[shCount]);       // 000CCCCC:BBBAAAAA
5769
5770       emitcode ("xrl", "a,%s", x);      // BBB(CCCCC^AAAAA):BBBAAAAA
5771
5772       emitcode ("xch", "a,%s", x);      // BBBAAAAA:BBB(CCCCC^AAAAA)
5773
5774       emitcode ("anl", "a,#0x%02x",
5775                 SRMask[shCount]);       // 000AAAAA:BBB(CCCCC^AAAAA)
5776
5777       emitcode ("xch", "a,%s", x);      // BBB(CCCCC^AAAAA):000AAAAA
5778
5779       emitcode ("xrl", "a,%s", x);      // BBBCCCCC:000AAAAA
5780
5781       emitcode ("xch", "a,%s", x);      // 000SAAAA:BBBCCCCC
5782
5783       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5784       emitcode ("orl", "a,#0x%02x",
5785                 (unsigned char) ~SRMask[shCount]);      // 111AAAAA:BBBCCCCC
5786
5787       emitcode ("", "%05d$:", tlbl->key + 100);
5788       break;                    // SSSSAAAA:BBBCCCCC
5789
5790     case 6:                     // AABBBBBB:CCDDDDDD
5791
5792       tlbl = newiTempLabel (NULL);
5793       emitcode ("mov", "c,acc.7");
5794       AccAXLrl1 (x);            // ABBBBBBC:CDDDDDDA
5795
5796       AccAXLrl1 (x);            // BBBBBBCC:DDDDDDAA
5797
5798       emitcode ("xch", "a,%s", x);      // DDDDDDAA:BBBBBBCC
5799
5800       emitcode ("anl", "a,#0x%02x",
5801                 SRMask[shCount]);       // 000000AA:BBBBBBCC
5802
5803       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5804       emitcode ("orl", "a,#0x%02x",
5805                 (unsigned char) ~SRMask[shCount]);      // 111111AA:BBBBBBCC
5806
5807       emitcode ("", "%05d$:", tlbl->key + 100);
5808       break;
5809     case 7:                     // ABBBBBBB:CDDDDDDD
5810
5811       tlbl = newiTempLabel (NULL);
5812       emitcode ("mov", "c,acc.7");      // c = A
5813
5814       AccAXLrl1 (x);            // BBBBBBBC:DDDDDDDA
5815
5816       emitcode ("xch", "a,%s", x);      // DDDDDDDA:BBBBBBCC
5817
5818       emitcode ("anl", "a,#0x%02x",
5819                 SRMask[shCount]);       // 0000000A:BBBBBBBC
5820
5821       emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5822       emitcode ("orl", "a,#0x%02x",
5823                 (unsigned char) ~SRMask[shCount]);      // 1111111A:BBBBBBBC
5824
5825       emitcode ("", "%05d$:", tlbl->key + 100);
5826       break;
5827     default:
5828       break;
5829     }
5830 }
5831
5832 /*-----------------------------------------------------------------*/
5833 /* shiftL2Left2Result - shift left two bytes from left to result   */
5834 /*-----------------------------------------------------------------*/
5835 static void
5836 shiftL2Left2Result (operand * left, int offl,
5837                     operand * result, int offr, int shCount)
5838 {
5839   if (sameRegs (AOP (result), AOP (left)) &&
5840       ((offl + MSB16) == offr))
5841     {
5842       /* don't crash result[offr] */
5843       MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5844       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5845     }
5846   else
5847     {
5848       movLeft2Result (left, offl, result, offr, 0);
5849       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5850     }
5851   /* ax << shCount (x = lsb(result)) */
5852   AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5853   aopPut (AOP (result), "a", offr + MSB16);
5854 }
5855
5856
5857 /*-----------------------------------------------------------------*/
5858 /* shiftR2Left2Result - shift right two bytes from left to result  */
5859 /*-----------------------------------------------------------------*/
5860 static void
5861 shiftR2Left2Result (operand * left, int offl,
5862                     operand * result, int offr,
5863                     int shCount, int sign)
5864 {
5865   if (sameRegs (AOP (result), AOP (left)) &&
5866       ((offl + MSB16) == offr))
5867     {
5868       /* don't crash result[offr] */
5869       MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5870       emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5871     }
5872   else
5873     {
5874       movLeft2Result (left, offl, result, offr, 0);
5875       MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5876     }
5877   /* a:x >> shCount (x = lsb(result)) */
5878   if (sign)
5879     AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5880   else
5881     AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5882   if (getDataSize (result) > 1)
5883     aopPut (AOP (result), "a", offr + MSB16);
5884 }
5885
5886 /*-----------------------------------------------------------------*/
5887 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5888 /*-----------------------------------------------------------------*/
5889 static void
5890 shiftLLeftOrResult (operand * left, int offl,
5891                     operand * result, int offr, int shCount)
5892 {
5893   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5894   /* shift left accumulator */
5895   AccLsh (shCount);
5896   /* or with result */
5897   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5898   /* back to result */
5899   aopPut (AOP (result), "a", offr);
5900 }
5901
5902 /*-----------------------------------------------------------------*/
5903 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5904 /*-----------------------------------------------------------------*/
5905 static void
5906 shiftRLeftOrResult (operand * left, int offl,
5907                     operand * result, int offr, int shCount)
5908 {
5909   MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5910   /* shift right accumulator */
5911   AccRsh (shCount);
5912   /* or with result */
5913   emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5914   /* back to result */
5915   aopPut (AOP (result), "a", offr);
5916 }
5917
5918 /*-----------------------------------------------------------------*/
5919 /* genlshOne - left shift a one byte quantity by known count       */
5920 /*-----------------------------------------------------------------*/
5921 static void
5922 genlshOne (operand * result, operand * left, int shCount)
5923 {
5924   shiftL1Left2Result (left, LSB, result, LSB, shCount);
5925 }
5926
5927 /*-----------------------------------------------------------------*/
5928 /* genlshTwo - left shift two bytes by known amount != 0           */
5929 /*-----------------------------------------------------------------*/
5930 static void
5931 genlshTwo (operand * result, operand * left, int shCount)
5932 {
5933   int size;
5934
5935   size = getDataSize (result);
5936
5937   /* if shCount >= 8 */
5938   if (shCount >= 8)
5939     {
5940       shCount -= 8;
5941
5942       if (size > 1)
5943         {
5944           if (shCount)
5945             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5946           else
5947             movLeft2Result (left, LSB, result, MSB16, 0);
5948         }
5949       aopPut (AOP (result), zero, LSB);
5950     }
5951
5952   /*  1 <= shCount <= 7 */
5953   else
5954     {
5955       if (size == 1)
5956         shiftL1Left2Result (left, LSB, result, LSB, shCount);
5957       else
5958         shiftL2Left2Result (left, LSB, result, LSB, shCount);
5959     }
5960 }
5961
5962 /*-----------------------------------------------------------------*/
5963 /* shiftLLong - shift left one long from left to result            */
5964 /* offl = LSB or MSB16                                             */
5965 /*-----------------------------------------------------------------*/
5966 static void
5967 shiftLLong (operand * left, operand * result, int offr)
5968 {
5969   char *l;
5970   int size = AOP_SIZE (result);
5971
5972   if (size >= LSB + offr)
5973     {
5974       l = aopGet (AOP (left), LSB, FALSE, FALSE);
5975       MOVA (l);
5976       emitcode ("add", "a,acc");
5977       if (sameRegs (AOP (left), AOP (result)) &&
5978           size >= MSB16 + offr && offr != LSB)
5979         emitcode ("xch", "a,%s",
5980                   aopGet (AOP (left), LSB + offr, FALSE, FALSE));
5981       else
5982         aopPut (AOP (result), "a", LSB + offr);
5983     }
5984
5985   if (size >= MSB16 + offr)
5986     {
5987       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
5988         {
5989           l = aopGet (AOP (left), MSB16, FALSE, FALSE);
5990           MOVA (l);
5991         }
5992       emitcode ("rlc", "a");
5993       if (sameRegs (AOP (left), AOP (result)) &&
5994           size >= MSB24 + offr && offr != LSB)
5995         emitcode ("xch", "a,%s",
5996                   aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
5997       else
5998         aopPut (AOP (result), "a", MSB16 + offr);
5999     }
6000
6001   if (size >= MSB24 + offr)
6002     {
6003       if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6004         {
6005           l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6006           MOVA (l);
6007         }
6008       emitcode ("rlc", "a");
6009       if (sameRegs (AOP (left), AOP (result)) &&
6010           size >= MSB32 + offr && offr != LSB)
6011         emitcode ("xch", "a,%s",
6012                   aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6013       else
6014         aopPut (AOP (result), "a", MSB24 + offr);
6015     }
6016
6017   if (size > MSB32 + offr)
6018     {
6019       if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6020         {
6021           l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6022           MOVA (l);
6023         }
6024       emitcode ("rlc", "a");
6025       aopPut (AOP (result), "a", MSB32 + offr);
6026     }
6027   if (offr != LSB)
6028     aopPut (AOP (result), zero, LSB);
6029 }
6030
6031 /*-----------------------------------------------------------------*/
6032 /* genlshFour - shift four byte by a known amount != 0             */
6033 /*-----------------------------------------------------------------*/
6034 static void
6035 genlshFour (operand * result, operand * left, int shCount)
6036 {
6037   int size;
6038
6039   size = AOP_SIZE (result);
6040
6041   /* if shifting more that 3 bytes */
6042   if (shCount >= 24)
6043     {
6044       shCount -= 24;
6045       if (shCount)
6046         /* lowest order of left goes to the highest
6047            order of the destination */
6048         shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6049       else
6050         movLeft2Result (left, LSB, result, MSB32, 0);
6051       aopPut (AOP (result), zero, LSB);
6052       aopPut (AOP (result), zero, MSB16);
6053       aopPut (AOP (result), zero, MSB24);
6054       return;
6055     }
6056
6057   /* more than two bytes */
6058   else if (shCount >= 16)
6059     {
6060       /* lower order two bytes goes to higher order two bytes */
6061       shCount -= 16;
6062       /* if some more remaining */
6063       if (shCount)
6064         shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6065       else
6066         {
6067           movLeft2Result (left, MSB16, result, MSB32, 0);
6068           movLeft2Result (left, LSB, result, MSB24, 0);
6069         }
6070       aopPut (AOP (result), zero, MSB16);
6071       aopPut (AOP (result), zero, LSB);
6072       return;
6073     }
6074
6075   /* if more than 1 byte */
6076   else if (shCount >= 8)
6077     {
6078       /* lower order three bytes goes to higher order  three bytes */
6079       shCount -= 8;
6080       if (size == 2)
6081         {
6082           if (shCount)
6083             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6084           else
6085             movLeft2Result (left, LSB, result, MSB16, 0);
6086         }
6087       else
6088         {                       /* size = 4 */
6089           if (shCount == 0)
6090             {
6091               movLeft2Result (left, MSB24, result, MSB32, 0);
6092               movLeft2Result (left, MSB16, result, MSB24, 0);
6093               movLeft2Result (left, LSB, result, MSB16, 0);
6094               aopPut (AOP (result), zero, LSB);
6095             }
6096           else if (shCount == 1)
6097             shiftLLong (left, result, MSB16);
6098           else
6099             {
6100               shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6101               shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6102               shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6103               aopPut (AOP (result), zero, LSB);
6104             }
6105         }
6106     }
6107
6108   /* 1 <= shCount <= 7 */
6109   else if (shCount <= 2)
6110     {
6111       shiftLLong (left, result, LSB);
6112       if (shCount == 2)
6113         shiftLLong (result, result, LSB);
6114     }
6115   /* 3 <= shCount <= 7, optimize */
6116   else
6117     {
6118       shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6119       shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6120       shiftL2Left2Result (left, LSB, result, LSB, shCount);
6121     }
6122 }
6123
6124 /*-----------------------------------------------------------------*/
6125 /* genLeftShiftLiteral - left shifting by known count              */
6126 /*-----------------------------------------------------------------*/
6127 static void
6128 genLeftShiftLiteral (operand * left,
6129                      operand * right,
6130                      operand * result,
6131                      iCode * ic)
6132 {
6133   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6134   int size;
6135
6136   freeAsmop (right, NULL, ic, TRUE);
6137
6138   aopOp (left, ic, FALSE);
6139   aopOp (result, ic, FALSE);
6140
6141   size = getSize (operandType (result));
6142
6143 #if VIEW_SIZE
6144   emitcode ("; shift left ", "result %d, left %d", size,
6145             AOP_SIZE (left));
6146 #endif
6147
6148   /* I suppose that the left size >= result size */
6149   if (shCount == 0)
6150     {
6151       while (size--)
6152         {
6153           movLeft2Result (left, size, result, size, 0);
6154         }
6155     }
6156
6157   else if (shCount >= (size * 8))
6158     while (size--)
6159       aopPut (AOP (result), zero, size);
6160   else
6161     {
6162       switch (size)
6163         {
6164         case 1:
6165           genlshOne (result, left, shCount);
6166           break;
6167
6168         case 2:
6169           genlshTwo (result, left, shCount);
6170           break;
6171
6172         case 4:
6173           genlshFour (result, left, shCount);
6174           break;
6175         default:
6176           fprintf(stderr, "*** ack! mystery literal shift!\n");
6177           break;
6178         }
6179     }
6180   freeAsmop (left, NULL, ic, TRUE);
6181   freeAsmop (result, NULL, ic, TRUE);
6182 }
6183
6184 /*-----------------------------------------------------------------*/
6185 /* genLeftShift - generates code for left shifting                 */
6186 /*-----------------------------------------------------------------*/
6187 static void
6188 genLeftShift (iCode * ic)
6189 {
6190   operand *left, *right, *result;
6191   int size, offset;
6192   char *l;
6193   symbol *tlbl, *tlbl1;
6194
6195   right = IC_RIGHT (ic);
6196   left = IC_LEFT (ic);
6197   result = IC_RESULT (ic);
6198
6199   aopOp (right, ic, FALSE);
6200
6201   /* if the shift count is known then do it
6202      as efficiently as possible */
6203   if (AOP_TYPE (right) == AOP_LIT)
6204     {
6205       genLeftShiftLiteral (left, right, result, ic);
6206       return;
6207     }
6208
6209   /* shift count is unknown then we have to form
6210      a loop get the loop count in B : Note: we take
6211      only the lower order byte since shifting
6212      more that 32 bits make no sense anyway, ( the
6213      largest size of an object can be only 32 bits ) */
6214
6215   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6216   emitcode ("inc", "b");
6217   freeAsmop (right, NULL, ic, TRUE);
6218   aopOp (left, ic, FALSE);
6219   aopOp (result, ic, FALSE);
6220
6221   /* now move the left to the result if they are not the
6222      same */
6223   if (!sameRegs (AOP (left), AOP (result)) &&
6224       AOP_SIZE (result) > 1)
6225     {
6226
6227       size = AOP_SIZE (result);
6228       offset = 0;
6229       while (size--)
6230         {
6231           l = aopGet (AOP (left), offset, FALSE, TRUE);
6232           if (*l == '@' && (IS_AOP_PREG (result)))
6233             {
6234
6235               emitcode ("mov", "a,%s", l);
6236               aopPut (AOP (result), "a", offset);
6237             }
6238           else
6239             aopPut (AOP (result), l, offset);
6240           offset++;
6241         }
6242     }
6243
6244   tlbl = newiTempLabel (NULL);
6245   size = AOP_SIZE (result);
6246   offset = 0;
6247   tlbl1 = newiTempLabel (NULL);
6248
6249   /* if it is only one byte then */
6250   if (size == 1)
6251     {
6252       symbol *tlbl1 = newiTempLabel (NULL);
6253
6254       l = aopGet (AOP (left), 0, FALSE, FALSE);
6255       MOVA (l);
6256       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6257       emitcode ("", "%05d$:", tlbl->key + 100);
6258       emitcode ("add", "a,acc");
6259       emitcode ("", "%05d$:", tlbl1->key + 100);
6260       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6261       aopPut (AOP (result), "a", 0);
6262       goto release;
6263     }
6264
6265   reAdjustPreg (AOP (result));
6266
6267   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6268   emitcode ("", "%05d$:", tlbl->key + 100);
6269   l = aopGet (AOP (result), offset, FALSE, FALSE);
6270   MOVA (l);
6271   emitcode ("add", "a,acc");
6272   aopPut (AOP (result), "a", offset++);
6273   while (--size)
6274     {
6275       l = aopGet (AOP (result), offset, FALSE, FALSE);
6276       MOVA (l);
6277       emitcode ("rlc", "a");
6278       aopPut (AOP (result), "a", offset++);
6279     }
6280   reAdjustPreg (AOP (result));
6281
6282   emitcode ("", "%05d$:", tlbl1->key + 100);
6283   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6284 release:
6285   freeAsmop (left, NULL, ic, TRUE);
6286   freeAsmop (result, NULL, ic, TRUE);
6287 }
6288
6289 /*-----------------------------------------------------------------*/
6290 /* genrshOne - right shift a one byte quantity by known count      */
6291 /*-----------------------------------------------------------------*/
6292 static void
6293 genrshOne (operand * result, operand * left,
6294            int shCount, int sign)
6295 {
6296   shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6297 }
6298
6299 /*-----------------------------------------------------------------*/
6300 /* genrshTwo - right shift two bytes by known amount != 0          */
6301 /*-----------------------------------------------------------------*/
6302 static void
6303 genrshTwo (operand * result, operand * left,
6304            int shCount, int sign)
6305 {
6306   /* if shCount >= 8 */
6307   if (shCount >= 8)
6308     {
6309       shCount -= 8;
6310       if (shCount)
6311         shiftR1Left2Result (left, MSB16, result, LSB,
6312                             shCount, sign);
6313       else
6314         movLeft2Result (left, MSB16, result, LSB, sign);
6315       addSign (result, MSB16, sign);
6316     }
6317
6318   /*  1 <= shCount <= 7 */
6319   else
6320     shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6321 }
6322
6323 /*-----------------------------------------------------------------*/
6324 /* shiftRLong - shift right one long from left to result           */
6325 /* offl = LSB or MSB16                                             */
6326 /*-----------------------------------------------------------------*/
6327 static void
6328 shiftRLong (operand * left, int offl,
6329             operand * result, int sign)
6330 {
6331   int isSameRegs=sameRegs(AOP(left),AOP(result));
6332
6333   if (isSameRegs && offl>1) {
6334     // we are in big trouble, but this shouldn't happen
6335     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6336   }
6337
6338   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6339   
6340   if (offl==MSB16) {
6341     // shift is > 8
6342     if (sign) {
6343       emitcode ("rlc", "a");
6344       emitcode ("subb", "a,acc");
6345       emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6346     } else {
6347       aopPut (AOP(result), zero, MSB32);
6348     }
6349   }
6350
6351   if (!sign) {
6352     emitcode ("clr", "c");
6353   } else {
6354     emitcode ("mov", "c,acc.7");
6355   }
6356
6357   emitcode ("rrc", "a");
6358
6359   if (isSameRegs && offl==MSB16) {
6360     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6361   } else {
6362     aopPut (AOP (result), "a", MSB32);
6363     MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6364   }
6365
6366   emitcode ("rrc", "a");
6367   if (isSameRegs && offl==1) {
6368     emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6369   } else {
6370     aopPut (AOP (result), "a", MSB24);
6371     MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6372   }
6373   emitcode ("rrc", "a");
6374   aopPut (AOP (result), "a", MSB16 - offl);
6375
6376   if (offl == LSB)
6377     {
6378       MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6379       emitcode ("rrc", "a");
6380       aopPut (AOP (result), "a", LSB);
6381     }
6382 }
6383
6384 /*-----------------------------------------------------------------*/
6385 /* genrshFour - shift four byte by a known amount != 0             */
6386 /*-----------------------------------------------------------------*/
6387 static void
6388 genrshFour (operand * result, operand * left,
6389             int shCount, int sign)
6390 {
6391   /* if shifting more that 3 bytes */
6392   if (shCount >= 24)
6393     {
6394       shCount -= 24;
6395       if (shCount)
6396         shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6397       else
6398         movLeft2Result (left, MSB32, result, LSB, sign);
6399       addSign (result, MSB16, sign);
6400     }
6401   else if (shCount >= 16)
6402     {
6403       shCount -= 16;
6404       if (shCount)
6405         shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6406       else
6407         {
6408           movLeft2Result (left, MSB24, result, LSB, 0);
6409           movLeft2Result (left, MSB32, result, MSB16, sign);
6410         }
6411       addSign (result, MSB24, sign);
6412     }
6413   else if (shCount >= 8)
6414     {
6415       shCount -= 8;
6416       if (shCount == 1)
6417         shiftRLong (left, MSB16, result, sign);
6418       else if (shCount == 0)
6419         {
6420           movLeft2Result (left, MSB16, result, LSB, 0);
6421           movLeft2Result (left, MSB24, result, MSB16, 0);
6422           movLeft2Result (left, MSB32, result, MSB24, sign);
6423           addSign (result, MSB32, sign);
6424         }
6425       else
6426         {
6427           shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6428           shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6429           /* the last shift is signed */
6430           shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6431           addSign (result, MSB32, sign);
6432         }
6433     }
6434   else
6435     {                           /* 1 <= shCount <= 7 */
6436       if (shCount <= 2)
6437         {
6438           shiftRLong (left, LSB, result, sign);
6439           if (shCount == 2)
6440             shiftRLong (result, LSB, result, sign);
6441         }
6442       else
6443         {
6444           shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6445           shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6446           shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6447         }
6448     }
6449 }
6450
6451 /*-----------------------------------------------------------------*/
6452 /* genRightShiftLiteral - right shifting by known count            */
6453 /*-----------------------------------------------------------------*/
6454 static void
6455 genRightShiftLiteral (operand * left,
6456                       operand * right,
6457                       operand * result,
6458                       iCode * ic,
6459                       int sign)
6460 {
6461   int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6462   int size;
6463
6464   freeAsmop (right, NULL, ic, TRUE);
6465
6466   aopOp (left, ic, FALSE);
6467   aopOp (result, ic, FALSE);
6468
6469 #if VIEW_SIZE
6470   emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6471             AOP_SIZE (left));
6472 #endif
6473
6474   size = getDataSize (left);
6475   /* test the LEFT size !!! */
6476
6477   /* I suppose that the left size >= result size */
6478   if (shCount == 0)
6479     {
6480       size = getDataSize (result);
6481       while (size--)
6482         movLeft2Result (left, size, result, size, 0);
6483     }
6484
6485   else if (shCount >= (size * 8))
6486     {
6487       if (sign)
6488         /* get sign in acc.7 */
6489         MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6490       addSign (result, LSB, sign);
6491     }
6492   else
6493     {
6494       switch (size)
6495         {
6496         case 1:
6497           genrshOne (result, left, shCount, sign);
6498           break;
6499
6500         case 2:
6501           genrshTwo (result, left, shCount, sign);
6502           break;
6503
6504         case 4:
6505           genrshFour (result, left, shCount, sign);
6506           break;
6507         default:
6508           break;
6509         }
6510
6511       freeAsmop (left, NULL, ic, TRUE);
6512       freeAsmop (result, NULL, ic, TRUE);
6513     }
6514 }
6515
6516 /*-----------------------------------------------------------------*/
6517 /* genSignedRightShift - right shift of signed number              */
6518 /*-----------------------------------------------------------------*/
6519 static void
6520 genSignedRightShift (iCode * ic)
6521 {
6522   operand *right, *left, *result;
6523   int size, offset;
6524   char *l;
6525   symbol *tlbl, *tlbl1;
6526
6527   /* we do it the hard way put the shift count in b
6528      and loop thru preserving the sign */
6529
6530   right = IC_RIGHT (ic);
6531   left = IC_LEFT (ic);
6532   result = IC_RESULT (ic);
6533
6534   aopOp (right, ic, FALSE);
6535
6536
6537   if (AOP_TYPE (right) == AOP_LIT)
6538     {
6539       genRightShiftLiteral (left, right, result, ic, 1);
6540       return;
6541     }
6542   /* shift count is unknown then we have to form
6543      a loop get the loop count in B : Note: we take
6544      only the lower order byte since shifting
6545      more that 32 bits make no sense anyway, ( the
6546      largest size of an object can be only 32 bits ) */
6547
6548   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6549   emitcode ("inc", "b");
6550   freeAsmop (right, NULL, ic, TRUE);
6551   aopOp (left, ic, FALSE);
6552   aopOp (result, ic, FALSE);
6553
6554   /* now move the left to the result if they are not the
6555      same */
6556   if (!sameRegs (AOP (left), AOP (result)) &&
6557       AOP_SIZE (result) > 1)
6558     {
6559
6560       size = AOP_SIZE (result);
6561       offset = 0;
6562       while (size--)
6563         {
6564           l = aopGet (AOP (left), offset, FALSE, TRUE);
6565           if (*l == '@' && IS_AOP_PREG (result))
6566             {
6567
6568               emitcode ("mov", "a,%s", l);
6569               aopPut (AOP (result), "a", offset);
6570             }
6571           else
6572             aopPut (AOP (result), l, offset);
6573           offset++;
6574         }
6575     }
6576
6577   /* mov the highest order bit to OVR */
6578   tlbl = newiTempLabel (NULL);
6579   tlbl1 = newiTempLabel (NULL);
6580
6581   size = AOP_SIZE (result);
6582   offset = size - 1;
6583   emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6584   emitcode ("rlc", "a");
6585   emitcode ("mov", "ov,c");
6586   /* if it is only one byte then */
6587   if (size == 1)
6588     {
6589       l = aopGet (AOP (left), 0, FALSE, FALSE);
6590       MOVA (l);
6591       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6592       emitcode ("", "%05d$:", tlbl->key + 100);
6593       emitcode ("mov", "c,ov");
6594       emitcode ("rrc", "a");
6595       emitcode ("", "%05d$:", tlbl1->key + 100);
6596       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6597       aopPut (AOP (result), "a", 0);
6598       goto release;
6599     }
6600
6601   reAdjustPreg (AOP (result));
6602   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6603   emitcode ("", "%05d$:", tlbl->key + 100);
6604   emitcode ("mov", "c,ov");
6605   while (size--)
6606     {
6607       l = aopGet (AOP (result), offset, FALSE, FALSE);
6608       MOVA (l);
6609       emitcode ("rrc", "a");
6610       aopPut (AOP (result), "a", offset--);
6611     }
6612   reAdjustPreg (AOP (result));
6613   emitcode ("", "%05d$:", tlbl1->key + 100);
6614   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6615
6616 release:
6617   freeAsmop (left, NULL, ic, TRUE);
6618   freeAsmop (result, NULL, ic, TRUE);
6619 }
6620
6621 /*-----------------------------------------------------------------*/
6622 /* genRightShift - generate code for right shifting                */
6623 /*-----------------------------------------------------------------*/
6624 static void
6625 genRightShift (iCode * ic)
6626 {
6627   operand *right, *left, *result;
6628   sym_link *retype;
6629   int size, offset;
6630   char *l;
6631   symbol *tlbl, *tlbl1;
6632
6633   /* if signed then we do it the hard way preserve the
6634      sign bit moving it inwards */
6635   retype = getSpec (operandType (IC_RESULT (ic)));
6636
6637   if (!SPEC_USIGN (retype))
6638     {
6639       genSignedRightShift (ic);
6640       return;
6641     }
6642
6643   /* signed & unsigned types are treated the same : i.e. the
6644      signed is NOT propagated inwards : quoting from the
6645      ANSI - standard : "for E1 >> E2, is equivalent to division
6646      by 2**E2 if unsigned or if it has a non-negative value,
6647      otherwise the result is implementation defined ", MY definition
6648      is that the sign does not get propagated */
6649
6650   right = IC_RIGHT (ic);
6651   left = IC_LEFT (ic);
6652   result = IC_RESULT (ic);
6653
6654   aopOp (right, ic, FALSE);
6655
6656   /* if the shift count is known then do it
6657      as efficiently as possible */
6658   if (AOP_TYPE (right) == AOP_LIT)
6659     {
6660       genRightShiftLiteral (left, right, result, ic, 0);
6661       return;
6662     }
6663
6664   /* shift count is unknown then we have to form
6665      a loop get the loop count in B : Note: we take
6666      only the lower order byte since shifting
6667      more that 32 bits make no sense anyway, ( the
6668      largest size of an object can be only 32 bits ) */
6669
6670   emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6671   emitcode ("inc", "b");
6672   freeAsmop (right, NULL, ic, TRUE);
6673   aopOp (left, ic, FALSE);
6674   aopOp (result, ic, FALSE);
6675
6676   /* now move the left to the result if they are not the
6677      same */
6678   if (!sameRegs (AOP (left), AOP (result)) &&
6679       AOP_SIZE (result) > 1)
6680     {
6681
6682       size = AOP_SIZE (result);
6683       offset = 0;
6684       while (size--)
6685         {
6686           l = aopGet (AOP (left), offset, FALSE, TRUE);
6687           if (*l == '@' && IS_AOP_PREG (result))
6688             {
6689
6690               emitcode ("mov", "a,%s", l);
6691               aopPut (AOP (result), "a", offset);
6692             }
6693           else
6694             aopPut (AOP (result), l, offset);
6695           offset++;
6696         }
6697     }
6698
6699   tlbl = newiTempLabel (NULL);
6700   tlbl1 = newiTempLabel (NULL);
6701   size = AOP_SIZE (result);
6702   offset = size - 1;
6703
6704   /* if it is only one byte then */
6705   if (size == 1)
6706     {
6707       l = aopGet (AOP (left), 0, FALSE, FALSE);
6708       MOVA (l);
6709       emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6710       emitcode ("", "%05d$:", tlbl->key + 100);
6711       CLRC;
6712       emitcode ("rrc", "a");
6713       emitcode ("", "%05d$:", tlbl1->key + 100);
6714       emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6715       aopPut (AOP (result), "a", 0);
6716       goto release;
6717     }
6718
6719   reAdjustPreg (AOP (result));
6720   emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6721   emitcode ("", "%05d$:", tlbl->key + 100);
6722   CLRC;
6723   while (size--)
6724     {
6725       l = aopGet (AOP (result), offset, FALSE, FALSE);
6726       MOVA (l);
6727       emitcode ("rrc", "a");
6728       aopPut (AOP (result), "a", offset--);
6729     }
6730   reAdjustPreg (AOP (result));
6731
6732   emitcode ("", "%05d$:", tlbl1->key + 100);
6733   emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6734
6735 release:
6736   freeAsmop (left, NULL, ic, TRUE);
6737   freeAsmop (result, NULL, ic, TRUE);
6738 }
6739
6740 /*-----------------------------------------------------------------*/
6741 /* genUnpackBits - generates code for unpacking bits               */
6742 /*-----------------------------------------------------------------*/
6743 static void
6744 genUnpackBits (operand * result, char *rname, int ptype)
6745 {
6746   int shCnt;
6747   int rlen = 0;
6748   sym_link *etype;
6749   int offset = 0;
6750   int rsize;
6751
6752   etype = getSpec (operandType (result));
6753   rsize = getSize (operandType (result));
6754   /* read the first byte  */
6755   switch (ptype)
6756     {
6757
6758     case POINTER:
6759     case IPOINTER:
6760       emitcode ("mov", "a,@%s", rname);
6761       break;
6762
6763     case PPOINTER:
6764       emitcode ("movx", "a,@%s", rname);
6765       break;
6766
6767     case FPOINTER:
6768       emitcode ("movx", "a,@dptr");
6769       break;
6770
6771     case CPOINTER:
6772       emitcode ("clr", "a");
6773       emitcode ("movc", "a,%s", "@a+dptr");
6774       break;
6775
6776     case GPOINTER:
6777       emitcode ("lcall", "__gptrget");
6778       break;
6779     }
6780
6781   rlen = SPEC_BLEN (etype);
6782
6783   /* if we have bitdisplacement then it fits   */
6784   /* into this byte completely or if length is */
6785   /* less than a byte                          */
6786   if ((shCnt = SPEC_BSTR (etype)) ||
6787       (SPEC_BLEN (etype) <= 8))
6788     {
6789
6790       /* shift right acc */
6791       AccRsh (shCnt);
6792
6793       emitcode ("anl", "a,#0x%02x",
6794                 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6795       aopPut (AOP (result), "a", offset++);
6796       goto finish;
6797     }
6798
6799   /* bit field did not fit in a byte  */
6800   aopPut (AOP (result), "a", offset++);
6801
6802   while (1)
6803     {
6804
6805       switch (ptype)
6806         {
6807         case POINTER:
6808         case IPOINTER:
6809           emitcode ("inc", "%s", rname);
6810           emitcode ("mov", "a,@%s", rname);
6811           break;
6812
6813         case PPOINTER:
6814           emitcode ("inc", "%s", rname);
6815           emitcode ("movx", "a,@%s", rname);
6816           break;
6817
6818         case FPOINTER:
6819           emitcode ("inc", "dptr");
6820           emitcode ("movx", "a,@dptr");
6821           break;
6822
6823         case CPOINTER:
6824           emitcode ("clr", "a");
6825           emitcode ("inc", "dptr");
6826           emitcode ("movc", "a", "@a+dptr");
6827           break;
6828
6829         case GPOINTER:
6830           emitcode ("inc", "dptr");
6831           emitcode ("lcall", "__gptrget");
6832           break;
6833         }
6834
6835       rlen -= 8;
6836       /* if we are done */
6837       if (rlen < 8)
6838         break;
6839
6840       aopPut (AOP (result), "a", offset++);
6841
6842     }
6843
6844   if (rlen)
6845     {
6846       //  emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6847       AccLsh (8 - rlen);
6848       aopPut (AOP (result), "a", offset++);
6849     }
6850
6851 finish:
6852   if (offset < rsize)
6853     {
6854       rsize -= offset;
6855       while (rsize--)
6856         aopPut (AOP (result), zero, offset++);
6857     }
6858   return;
6859 }
6860
6861
6862 /*-----------------------------------------------------------------*/
6863 /* genDataPointerGet - generates code when ptr offset is known     */
6864 /*-----------------------------------------------------------------*/
6865 static void
6866 genDataPointerGet (operand * left,
6867                    operand * result,
6868                    iCode * ic)
6869 {
6870   char *l;
6871   char buffer[256];
6872   int size, offset = 0;
6873   aopOp (result, ic, TRUE);
6874
6875   /* get the string representation of the name */
6876   l = aopGet (AOP (left), 0, FALSE, TRUE);
6877   size = AOP_SIZE (result);
6878   while (size--)
6879     {
6880       if (offset)
6881         sprintf (buffer, "(%s + %d)", l + 1, offset);
6882       else
6883         sprintf (buffer, "%s", l + 1);
6884       aopPut (AOP (result), buffer, offset++);
6885     }
6886
6887   freeAsmop (left, NULL, ic, TRUE);
6888   freeAsmop (result, NULL, ic, TRUE);
6889 }
6890
6891 /*-----------------------------------------------------------------*/
6892 /* genNearPointerGet - emitcode for near pointer fetch             */
6893 /*-----------------------------------------------------------------*/
6894 static void
6895 genNearPointerGet (operand * left,
6896                    operand * result,
6897                    iCode * ic,
6898                    iCode * pi)
6899 {
6900   asmop *aop = NULL;
6901   regs *preg = NULL;
6902   char *rname;
6903   sym_link *rtype, *retype;
6904   sym_link *ltype = operandType (left);
6905   char buffer[80];
6906
6907   rtype = operandType (result);
6908   retype = getSpec (rtype);
6909
6910   aopOp (left, ic, FALSE);
6911
6912   /* if left is rematerialisable and
6913      result is not bit variable type and
6914      the left is pointer to data space i.e
6915      lower 128 bytes of space */
6916   if (AOP_TYPE (left) == AOP_IMMD &&
6917       !IS_BITVAR (retype) &&
6918       DCL_TYPE (ltype) == POINTER)
6919     {
6920       genDataPointerGet (left, result, ic);
6921       return;
6922     }
6923
6924   /* if the value is already in a pointer register
6925      then don't need anything more */
6926   if (!AOP_INPREG (AOP (left)))
6927     {
6928       /* otherwise get a free pointer register */
6929       aop = newAsmop (0);
6930       preg = getFreePtr (ic, &aop, FALSE);
6931       emitcode ("mov", "%s,%s",
6932                 preg->name,
6933                 aopGet (AOP (left), 0, FALSE, TRUE));
6934       rname = preg->name;
6935     }
6936   else
6937     rname = aopGet (AOP (left), 0, FALSE, FALSE);
6938
6939   aopOp (result, ic, FALSE);
6940
6941   /* if bitfield then unpack the bits */
6942   if (IS_BITVAR (retype))
6943     genUnpackBits (result, rname, POINTER);
6944   else
6945     {
6946       /* we have can just get the values */
6947       int size = AOP_SIZE (result);
6948       int offset = 0;
6949
6950       while (size--)
6951         {
6952           if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
6953             {
6954
6955               emitcode ("mov", "a,@%s", rname);
6956               aopPut (AOP (result), "a", offset);
6957             }
6958           else
6959             {
6960               sprintf (buffer, "@%s", rname);
6961               aopPut (AOP (result), buffer, offset);
6962             }
6963           offset++;
6964           if (size || pi)
6965             emitcode ("inc", "%s", rname);
6966         }
6967     }
6968
6969   /* now some housekeeping stuff */
6970   if (aop)       /* we had to allocate for this iCode */
6971     {
6972       if (pi) { /* post increment present */
6973         aopPut(AOP ( left ),rname,0);
6974       }
6975       freeAsmop (NULL, aop, ic, TRUE);
6976     }
6977   else
6978     {
6979       /* we did not allocate which means left
6980          already in a pointer register, then
6981          if size > 0 && this could be used again
6982          we have to point it back to where it
6983          belongs */
6984       if ((AOP_SIZE (result) > 1 &&
6985            !OP_SYMBOL (left)->remat &&
6986            (OP_SYMBOL (left)->liveTo > ic->seq ||
6987             ic->depth)) &&
6988           !pi)
6989         {
6990           int size = AOP_SIZE (result) - 1;
6991           while (size--)
6992             emitcode ("dec", "%s", rname);
6993         }
6994     }
6995
6996   /* done */
6997   freeAsmop (left, NULL, ic, TRUE);
6998   freeAsmop (result, NULL, ic, TRUE);
6999   if (pi) pi->generated = 1;
7000 }
7001
7002 /*-----------------------------------------------------------------*/
7003 /* genPagedPointerGet - emitcode for paged pointer fetch           */
7004 /*-----------------------------------------------------------------*/
7005 static void
7006 genPagedPointerGet (operand * left,
7007                     operand * result,
7008                     iCode * ic,
7009                     iCode *pi)
7010 {
7011   asmop *aop = NULL;
7012   regs *preg = NULL;
7013   char *rname;
7014   sym_link *rtype, *retype;
7015
7016   rtype = operandType (result);
7017   retype = getSpec (rtype);
7018
7019   aopOp (left, ic, FALSE);
7020
7021   /* if the value is already in a pointer register
7022      then don't need anything more */
7023   if (!AOP_INPREG (AOP (left)))
7024     {
7025       /* otherwise get a free pointer register */
7026       aop = newAsmop (0);
7027       preg = getFreePtr (ic, &aop, FALSE);
7028       emitcode ("mov", "%s,%s",
7029                 preg->name,
7030                 aopGet (AOP (left), 0, FALSE, TRUE));
7031       rname = preg->name;
7032     }
7033   else
7034     rname = aopGet (AOP (left), 0, FALSE, FALSE);
7035
7036   aopOp (result, ic, FALSE);
7037
7038   /* if bitfield then unpack the bits */
7039   if (IS_BITVAR (retype))
7040     genUnpackBits (result, rname, PPOINTER);
7041   else
7042     {
7043       /* we have can just get the values */
7044       int size = AOP_SIZE (result);
7045       int offset = 0;
7046
7047       while (size--)
7048         {
7049
7050           emitcode ("movx", "a,@%s", rname);
7051           aopPut (AOP (result), "a", offset);
7052
7053           offset++;
7054
7055           if (size || pi)
7056             emitcode ("inc", "%s", rname);
7057         }
7058     }
7059
7060   /* now some housekeeping stuff */
7061   if (aop) /* we had to allocate for this iCode */
7062     {
7063       if (pi) aopPut ( AOP (left), rname, 0);
7064       freeAsmop (NULL, aop, ic, TRUE);
7065     }
7066   else
7067     {
7068       /* we did not allocate which means left
7069          already in a pointer register, then
7070          if size > 0 && this could be used again
7071          we have to point it back to where it
7072          belongs */
7073       if ((AOP_SIZE (result) > 1 &&
7074            !OP_SYMBOL (left)->remat &&
7075            (OP_SYMBOL (left)->liveTo > ic->seq ||
7076             ic->depth)) &&
7077           !pi)
7078         {
7079           int size = AOP_SIZE (result) - 1;
7080           while (size--)
7081             emitcode ("dec", "%s", rname);
7082         }
7083     }
7084
7085   /* done */
7086   freeAsmop (left, NULL, ic, TRUE);
7087   freeAsmop (result, NULL, ic, TRUE);
7088   if (pi) pi->generated = 1;
7089
7090 }
7091
7092 /*-----------------------------------------------------------------*/
7093 /* genFarPointerGet - gget value from far space                    */
7094 /*-----------------------------------------------------------------*/
7095 static void
7096 genFarPointerGet (operand * left,
7097                   operand * result, iCode * ic, iCode * pi)
7098 {
7099   int size, offset;
7100   sym_link *retype = getSpec (operandType (result));
7101
7102   aopOp (left, ic, FALSE);
7103
7104   /* if the operand is already in dptr
7105      then we do nothing else we move the value to dptr */
7106   if (AOP_TYPE (left) != AOP_STR)
7107     {
7108       /* if this is remateriazable */
7109       if (AOP_TYPE (left) == AOP_IMMD)
7110         emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7111       else
7112         {                       /* we need to get it byte by byte */
7113           emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7114           emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7115         }
7116     }
7117   /* so dptr know contains the address */
7118   aopOp (result, ic, FALSE);
7119
7120   /* if bit then unpack */
7121   if (IS_BITVAR (retype))
7122     genUnpackBits (result, "dptr", FPOINTER);
7123   else
7124     {
7125       size = AOP_SIZE (result);
7126       offset = 0;
7127
7128       while (size--)
7129         {
7130           emitcode ("movx", "a,@dptr");
7131           aopPut (AOP (result), "a", offset++);
7132           if (size || pi)
7133             emitcode ("inc", "dptr");
7134         }
7135     }
7136   
7137   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7138     aopPut ( AOP (left), "dpl", 0);
7139     aopPut ( AOP (left), "dph", 1);
7140     pi->generated = 1;
7141   }
7142   freeAsmop (left, NULL, ic, TRUE);
7143   freeAsmop (result, NULL, ic, TRUE);
7144 }
7145
7146 /*-----------------------------------------------------------------*/
7147 /* genCodePointerGet - gget value from code space                  */
7148 /*-----------------------------------------------------------------*/
7149 static void
7150 genCodePointerGet (operand * left,
7151                     operand * result, iCode * ic, iCode *pi)
7152 {
7153   int size, offset;
7154   sym_link *retype = getSpec (operandType (result));
7155
7156   aopOp (left, ic, FALSE);
7157
7158   /* if the operand is already in dptr
7159      then we do nothing else we move the value to dptr */
7160   if (AOP_TYPE (left) != AOP_STR)
7161     {
7162       /* if this is remateriazable */
7163       if (AOP_TYPE (left) == AOP_IMMD)
7164         emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7165       else
7166         {                       /* we need to get it byte by byte */
7167           emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7168           emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7169         }
7170     }
7171   /* so dptr know contains the address */
7172   aopOp (result, ic, FALSE);
7173
7174   /* if bit then unpack */
7175   if (IS_BITVAR (retype))
7176     genUnpackBits (result, "dptr", CPOINTER);
7177   else
7178     {
7179       size = AOP_SIZE (result);
7180       offset = 0;
7181
7182       while (size--)
7183         {
7184           emitcode ("clr", "a");
7185           emitcode ("movc", "a,@a+dptr");
7186           aopPut (AOP (result), "a", offset++);
7187           if (size || pi)
7188             emitcode ("inc", "dptr");
7189         }
7190     }
7191
7192   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7193     aopPut ( AOP (left), "dpl", 0);
7194     aopPut ( AOP (left), "dph", 1);
7195     pi->generated = 1;
7196   }
7197   freeAsmop (left, NULL, ic, TRUE);
7198   freeAsmop (result, NULL, ic, TRUE);
7199 }
7200
7201 /*-----------------------------------------------------------------*/
7202 /* genGenPointerGet - gget value from generic pointer space        */
7203 /*-----------------------------------------------------------------*/
7204 static void
7205 genGenPointerGet (operand * left,
7206                   operand * result, iCode * ic, iCode *pi)
7207 {
7208   int size, offset;
7209   sym_link *retype = getSpec (operandType (result));
7210
7211   aopOp (left, ic, FALSE);
7212
7213   /* if the operand is already in dptr
7214      then we do nothing else we move the value to dptr */
7215   if (AOP_TYPE (left) != AOP_STR)
7216     {
7217       /* if this is remateriazable */
7218       if (AOP_TYPE (left) == AOP_IMMD)
7219         {
7220           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7221           emitcode ("mov", "b,#%d", pointerCode (retype));
7222         }
7223       else
7224         {                       /* we need to get it byte by byte */
7225           emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7226           emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7227           emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7228         }
7229     }
7230   /* so dptr know contains the address */
7231   aopOp (result, ic, FALSE);
7232
7233   /* if bit then unpack */
7234   if (IS_BITVAR (retype))
7235     genUnpackBits (result, "dptr", GPOINTER);
7236   else
7237     {
7238       size = AOP_SIZE (result);
7239       offset = 0;
7240
7241       while (size--)
7242         {
7243           emitcode ("lcall", "__gptrget");
7244           aopPut (AOP (result), "a", offset++);
7245           if (size || pi)
7246             emitcode ("inc", "dptr");
7247         }
7248     }
7249
7250   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7251     aopPut ( AOP (left), "dpl", 0);
7252     aopPut ( AOP (left), "dph", 1);
7253     pi->generated = 1;
7254   }
7255   freeAsmop (left, NULL, ic, TRUE);
7256   freeAsmop (result, NULL, ic, TRUE);
7257 }
7258
7259 /*-----------------------------------------------------------------*/
7260 /* genPointerGet - generate code for pointer get                   */
7261 /*-----------------------------------------------------------------*/
7262 static void
7263 genPointerGet (iCode * ic, iCode *pi)
7264 {
7265   operand *left, *result;
7266   sym_link *type, *etype;
7267   int p_type;
7268
7269   left = IC_LEFT (ic);
7270   result = IC_RESULT (ic);
7271
7272   /* depending on the type of pointer we need to
7273      move it to the correct pointer register */
7274   type = operandType (left);
7275   etype = getSpec (type);
7276   /* if left is of type of pointer then it is simple */
7277   if (IS_PTR (type) && !IS_FUNC (type->next))
7278     p_type = DCL_TYPE (type);
7279   else
7280     {
7281       /* we have to go by the storage class */
7282       p_type = PTR_TYPE (SPEC_OCLS (etype));
7283     }
7284
7285   /* now that we have the pointer type we assign
7286      the pointer values */
7287   switch (p_type)
7288     {
7289
7290     case POINTER:
7291     case IPOINTER:
7292       genNearPointerGet (left, result, ic, pi);
7293       break;
7294
7295     case PPOINTER:
7296       genPagedPointerGet (left, result, ic, pi);
7297       break;
7298
7299     case FPOINTER:
7300       genFarPointerGet (left, result, ic, pi);
7301       break;
7302
7303     case CPOINTER:
7304       genCodePointerGet (left, result, ic, pi);
7305       break;
7306
7307     case GPOINTER:
7308       genGenPointerGet (left, result, ic, pi);
7309       break;
7310     }
7311
7312 }
7313
7314 /*-----------------------------------------------------------------*/
7315 /* genPackBits - generates code for packed bit storage             */
7316 /*-----------------------------------------------------------------*/
7317 static void
7318 genPackBits (sym_link * etype,
7319              operand * right,
7320              char *rname, int p_type)
7321 {
7322   int shCount = 0;
7323   int offset = 0;
7324   int rLen = 0;
7325   int blen, bstr;
7326   char *l;
7327
7328   blen = SPEC_BLEN (etype);
7329   bstr = SPEC_BSTR (etype);
7330
7331   l = aopGet (AOP (right), offset++, FALSE, FALSE);
7332   MOVA (l);
7333
7334   /* if the bit lenth is less than or    */
7335   /* it exactly fits a byte then         */
7336   if (SPEC_BLEN (etype) <= 8)
7337     {
7338       shCount = SPEC_BSTR (etype);
7339
7340       /* shift left acc */
7341       AccLsh (shCount);
7342
7343       if (SPEC_BLEN (etype) < 8)
7344         {                       /* if smaller than a byte */
7345
7346
7347           switch (p_type)
7348             {
7349             case POINTER:
7350               emitcode ("mov", "b,a");
7351               emitcode ("mov", "a,@%s", rname);
7352               break;
7353
7354             case FPOINTER:
7355               emitcode ("mov", "b,a");
7356               emitcode ("movx", "a,@dptr");
7357               break;
7358
7359             case GPOINTER:
7360               emitcode ("push", "b");
7361               emitcode ("push", "acc");
7362               emitcode ("lcall", "__gptrget");
7363               emitcode ("pop", "b");
7364               break;
7365             }
7366
7367           emitcode ("anl", "a,#0x%02x", (unsigned char)
7368                     ((unsigned char) (0xFF << (blen + bstr)) |
7369                      (unsigned char) (0xFF >> (8 - bstr))));
7370           emitcode ("orl", "a,b");
7371           if (p_type == GPOINTER)
7372             emitcode ("pop", "b");
7373         }
7374     }
7375
7376   switch (p_type)
7377     {
7378     case POINTER:
7379       emitcode ("mov", "@%s,a", rname);
7380       break;
7381
7382     case FPOINTER:
7383       emitcode ("movx", "@dptr,a");
7384       break;
7385
7386     case GPOINTER:
7387       emitcode ("lcall", "__gptrput");
7388       break;
7389     }
7390
7391   /* if we r done */
7392   if (SPEC_BLEN (etype) <= 8)
7393     return;
7394
7395   emitcode ("inc", "%s", rname);
7396   rLen = SPEC_BLEN (etype);
7397
7398   /* now generate for lengths greater than one byte */
7399   while (1)
7400     {
7401
7402       l = aopGet (AOP (right), offset++, FALSE, TRUE);
7403
7404       rLen -= 8;
7405       if (rLen < 8)
7406         break;
7407
7408       switch (p_type)
7409         {
7410         case POINTER:
7411           if (*l == '@')
7412             {
7413               MOVA (l);
7414               emitcode ("mov", "@%s,a", rname);
7415             }
7416           else
7417             emitcode ("mov", "@%s,%s", rname, l);
7418           break;
7419
7420         case FPOINTER:
7421           MOVA (l);
7422           emitcode ("movx", "@dptr,a");
7423           break;
7424
7425         case GPOINTER:
7426           MOVA (l);
7427           emitcode ("lcall", "__gptrput");
7428           break;
7429         }
7430       emitcode ("inc", "%s", rname);
7431     }
7432
7433   MOVA (l);
7434
7435   /* last last was not complete */
7436   if (rLen)
7437     {
7438       /* save the byte & read byte */
7439       switch (p_type)
7440         {
7441         case POINTER:
7442           emitcode ("mov", "b,a");
7443           emitcode ("mov", "a,@%s", rname);
7444           break;
7445
7446         case FPOINTER:
7447           emitcode ("mov", "b,a");
7448           emitcode ("movx", "a,@dptr");
7449           break;
7450
7451         case GPOINTER:
7452           emitcode ("push", "b");
7453           emitcode ("push", "acc");
7454           emitcode ("lcall", "__gptrget");
7455           emitcode ("pop", "b");
7456           break;
7457         }
7458
7459       emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7460       emitcode ("orl", "a,b");
7461     }
7462
7463   if (p_type == GPOINTER)
7464     emitcode ("pop", "b");
7465
7466   switch (p_type)
7467     {
7468
7469     case POINTER:
7470       emitcode ("mov", "@%s,a", rname);
7471       break;
7472
7473     case FPOINTER:
7474       emitcode ("movx", "@dptr,a");
7475       break;
7476
7477     case GPOINTER:
7478       emitcode ("lcall", "__gptrput");
7479       break;
7480     }
7481 }
7482 /*-----------------------------------------------------------------*/
7483 /* genDataPointerSet - remat pointer to data space                 */
7484 /*-----------------------------------------------------------------*/
7485 static void
7486 genDataPointerSet (operand * right,
7487                    operand * result,
7488                    iCode * ic)
7489 {
7490   int size, offset = 0;
7491   char *l, buffer[256];
7492
7493   aopOp (right, ic, FALSE);
7494
7495   l = aopGet (AOP (result), 0, FALSE, TRUE);
7496   size = AOP_SIZE (right);
7497   while (size--)
7498     {
7499       if (offset)
7500         sprintf (buffer, "(%s + %d)", l + 1, offset);
7501       else
7502         sprintf (buffer, "%s", l + 1);
7503       emitcode ("mov", "%s,%s", buffer,
7504                 aopGet (AOP (right), offset++, FALSE, FALSE));
7505     }
7506
7507   freeAsmop (right, NULL, ic, TRUE);
7508   freeAsmop (result, NULL, ic, TRUE);
7509 }
7510
7511 /*-----------------------------------------------------------------*/
7512 /* genNearPointerSet - emitcode for near pointer put                */
7513 /*-----------------------------------------------------------------*/
7514 static void
7515 genNearPointerSet (operand * right,
7516                    operand * result,
7517                    iCode * ic,
7518                    iCode * pi)
7519 {
7520   asmop *aop = NULL;
7521   regs *preg = NULL;
7522   char *rname, *l;
7523   sym_link *retype, *letype;
7524   sym_link *ptype = operandType (result);
7525
7526   retype = getSpec (operandType (right));
7527   letype = getSpec (ptype);
7528   aopOp (result, ic, FALSE);
7529
7530   /* if the result is rematerializable &
7531      in data space & not a bit variable */
7532   if (AOP_TYPE (result) == AOP_IMMD &&
7533       DCL_TYPE (ptype) == POINTER &&
7534       !IS_BITVAR (retype) &&
7535       !IS_BITVAR (letype))
7536     {
7537       genDataPointerSet (right, result, ic);
7538       return;
7539     }
7540
7541   /* if the value is already in a pointer register
7542      then don't need anything more */
7543   if (!AOP_INPREG (AOP (result)))
7544     {
7545       /* otherwise get a free pointer register */
7546       aop = newAsmop (0);
7547       preg = getFreePtr (ic, &aop, FALSE);
7548       emitcode ("mov", "%s,%s",
7549                 preg->name,
7550                 aopGet (AOP (result), 0, FALSE, TRUE));
7551       rname = preg->name;
7552     }
7553   else
7554     rname = aopGet (AOP (result), 0, FALSE, FALSE);
7555
7556   aopOp (right, ic, FALSE);
7557
7558   /* if bitfield then unpack the bits */
7559   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7560     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7561   else
7562     {
7563       /* we have can just get the values */
7564       int size = AOP_SIZE (right);
7565       int offset = 0;
7566
7567       while (size--)
7568         {
7569           l = aopGet (AOP (right), offset, FALSE, TRUE);
7570           if (*l == '@')
7571             {
7572               MOVA (l);
7573               emitcode ("mov", "@%s,a", rname);
7574             }
7575           else
7576             emitcode ("mov", "@%s,%s", rname, l);
7577           if (size || pi)
7578             emitcode ("inc", "%s", rname);
7579           offset++;
7580         }
7581     }
7582
7583   /* now some housekeeping stuff */
7584   if (aop) /* we had to allocate for this iCode */
7585     {
7586       if (pi) aopPut (AOP (result),rname,0);
7587       freeAsmop (NULL, aop, ic, TRUE);
7588     }
7589   else
7590     {
7591       /* we did not allocate which means left
7592          already in a pointer register, then
7593          if size > 0 && this could be used again
7594          we have to point it back to where it
7595          belongs */
7596       if ((AOP_SIZE (right) > 1 &&
7597            !OP_SYMBOL (result)->remat &&
7598            (OP_SYMBOL (result)->liveTo > ic->seq ||
7599             ic->depth)) &&
7600           !pi)
7601         {
7602           int size = AOP_SIZE (right) - 1;
7603           while (size--)
7604             emitcode ("dec", "%s", rname);
7605         }
7606     }
7607
7608   /* done */
7609   if (pi) pi->generated = 1;
7610   freeAsmop (result, NULL, ic, TRUE);
7611   freeAsmop (right, NULL, ic, TRUE);
7612 }
7613
7614 /*-----------------------------------------------------------------*/
7615 /* genPagedPointerSet - emitcode for Paged pointer put             */
7616 /*-----------------------------------------------------------------*/
7617 static void
7618 genPagedPointerSet (operand * right,
7619                     operand * result,
7620                     iCode * ic,
7621                     iCode * pi)
7622 {
7623   asmop *aop = NULL;
7624   regs *preg = NULL;
7625   char *rname, *l;
7626   sym_link *retype, *letype;
7627
7628   retype = getSpec (operandType (right));
7629   letype = getSpec (operandType (result));
7630
7631   aopOp (result, ic, FALSE);
7632
7633   /* if the value is already in a pointer register
7634      then don't need anything more */
7635   if (!AOP_INPREG (AOP (result)))
7636     {
7637       /* otherwise get a free pointer register */
7638       aop = newAsmop (0);
7639       preg = getFreePtr (ic, &aop, FALSE);
7640       emitcode ("mov", "%s,%s",
7641                 preg->name,
7642                 aopGet (AOP (result), 0, FALSE, TRUE));
7643       rname = preg->name;
7644     }
7645   else
7646     rname = aopGet (AOP (result), 0, FALSE, FALSE);
7647
7648   aopOp (right, ic, FALSE);
7649
7650   /* if bitfield then unpack the bits */
7651   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7652     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7653   else
7654     {
7655       /* we have can just get the values */
7656       int size = AOP_SIZE (right);
7657       int offset = 0;
7658
7659       while (size--)
7660         {
7661           l = aopGet (AOP (right), offset, FALSE, TRUE);
7662
7663           MOVA (l);
7664           emitcode ("movx", "@%s,a", rname);
7665
7666           if (size || pi)
7667             emitcode ("inc", "%s", rname);
7668
7669           offset++;
7670         }
7671     }
7672
7673   /* now some housekeeping stuff */
7674   if (aop) /* we had to allocate for this iCode */
7675     {
7676       if (pi) aopPut (AOP (result),rname,0);
7677       freeAsmop (NULL, aop, ic, TRUE);
7678     }
7679   else
7680     {
7681       /* we did not allocate which means left
7682          already in a pointer register, then
7683          if size > 0 && this could be used again
7684          we have to point it back to where it
7685          belongs */
7686       if (AOP_SIZE (right) > 1 &&
7687           !OP_SYMBOL (result)->remat &&
7688           (OP_SYMBOL (result)->liveTo > ic->seq ||
7689            ic->depth))
7690         {
7691           int size = AOP_SIZE (right) - 1;
7692           while (size--)
7693             emitcode ("dec", "%s", rname);
7694         }
7695     }
7696
7697   /* done */
7698   if (pi) pi->generated = 1;
7699   freeAsmop (result, NULL, ic, TRUE);
7700   freeAsmop (right, NULL, ic, TRUE);
7701
7702
7703 }
7704
7705 /*-----------------------------------------------------------------*/
7706 /* genFarPointerSet - set value from far space                     */
7707 /*-----------------------------------------------------------------*/
7708 static void
7709 genFarPointerSet (operand * right,
7710                   operand * result, iCode * ic, iCode * pi)
7711 {
7712   int size, offset;
7713   sym_link *retype = getSpec (operandType (right));
7714   sym_link *letype = getSpec (operandType (result));
7715   aopOp (result, ic, FALSE);
7716
7717   /* if the operand is already in dptr
7718      then we do nothing else we move the value to dptr */
7719   if (AOP_TYPE (result) != AOP_STR)
7720     {
7721       /* if this is remateriazable */
7722       if (AOP_TYPE (result) == AOP_IMMD)
7723         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7724       else
7725         {                       /* we need to get it byte by byte */
7726           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7727           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7728         }
7729     }
7730   /* so dptr know contains the address */
7731   aopOp (right, ic, FALSE);
7732
7733   /* if bit then unpack */
7734   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7735     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7736   else
7737     {
7738       size = AOP_SIZE (right);
7739       offset = 0;
7740
7741       while (size--)
7742         {
7743           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7744           MOVA (l);
7745           emitcode ("movx", "@dptr,a");
7746           if (size || pi)
7747             emitcode ("inc", "dptr");
7748         }
7749     }
7750   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7751     aopPut (AOP(result),"dpl",0);
7752     aopPut (AOP(result),"dph",1);
7753     pi->generated=1;
7754   }
7755   freeAsmop (result, NULL, ic, TRUE);
7756   freeAsmop (right, NULL, ic, TRUE);
7757 }
7758
7759 /*-----------------------------------------------------------------*/
7760 /* genGenPointerSet - set value from generic pointer space         */
7761 /*-----------------------------------------------------------------*/
7762 static void
7763 genGenPointerSet (operand * right,
7764                   operand * result, iCode * ic, iCode * pi)
7765 {
7766   int size, offset;
7767   sym_link *retype = getSpec (operandType (right));
7768   sym_link *letype = getSpec (operandType (result));
7769
7770   aopOp (result, ic, FALSE);
7771
7772   /* if the operand is already in dptr
7773      then we do nothing else we move the value to dptr */
7774   if (AOP_TYPE (result) != AOP_STR)
7775     {
7776       /* if this is remateriazable */
7777       if (AOP_TYPE (result) == AOP_IMMD)
7778         {
7779           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7780           emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7781         }
7782       else
7783         {                       /* we need to get it byte by byte */
7784           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7785           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7786           emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7787         }
7788     }
7789   /* so dptr know contains the address */
7790   aopOp (right, ic, FALSE);
7791
7792   /* if bit then unpack */
7793   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7794     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7795   else
7796     {
7797       size = AOP_SIZE (right);
7798       offset = 0;
7799
7800       while (size--)
7801         {
7802           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7803           MOVA (l);
7804           emitcode ("lcall", "__gptrput");
7805           if (size || pi)
7806             emitcode ("inc", "dptr");
7807         }
7808     }
7809
7810   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7811     aopPut (AOP(result),"dpl",0);
7812     aopPut (AOP(result),"dph",1);
7813     pi->generated=1;
7814   }
7815   freeAsmop (result, NULL, ic, TRUE);
7816   freeAsmop (right, NULL, ic, TRUE);
7817 }
7818
7819 /*-----------------------------------------------------------------*/
7820 /* genPointerSet - stores the value into a pointer location        */
7821 /*-----------------------------------------------------------------*/
7822 static void
7823 genPointerSet (iCode * ic, iCode *pi)
7824 {
7825   operand *right, *result;
7826   sym_link *type, *etype;
7827   int p_type;
7828
7829   right = IC_RIGHT (ic);
7830   result = IC_RESULT (ic);
7831
7832   /* depending on the type of pointer we need to
7833      move it to the correct pointer register */
7834   type = operandType (result);
7835   etype = getSpec (type);
7836   /* if left is of type of pointer then it is simple */
7837   if (IS_PTR (type) && !IS_FUNC (type->next))
7838     {
7839       p_type = DCL_TYPE (type);
7840     }
7841   else
7842     {
7843       /* we have to go by the storage class */
7844       p_type = PTR_TYPE (SPEC_OCLS (etype));
7845     }
7846
7847   /* now that we have the pointer type we assign
7848      the pointer values */
7849   switch (p_type)
7850     {
7851
7852     case POINTER:
7853     case IPOINTER:
7854       genNearPointerSet (right, result, ic, pi);
7855       break;
7856
7857     case PPOINTER:
7858       genPagedPointerSet (right, result, ic, pi);
7859       break;
7860
7861     case FPOINTER:
7862       genFarPointerSet (right, result, ic, pi);
7863       break;
7864
7865     case GPOINTER:
7866       genGenPointerSet (right, result, ic, pi);
7867       break;
7868     }
7869
7870 }
7871
7872 /*-----------------------------------------------------------------*/
7873 /* genIfx - generate code for Ifx statement                        */
7874 /*-----------------------------------------------------------------*/
7875 static void
7876 genIfx (iCode * ic, iCode * popIc)
7877 {
7878   operand *cond = IC_COND (ic);
7879   int isbit = 0;
7880
7881   aopOp (cond, ic, FALSE);
7882
7883   /* get the value into acc */
7884   if (AOP_TYPE (cond) != AOP_CRY)
7885     toBoolean (cond);
7886   else
7887     isbit = 1;
7888   /* the result is now in the accumulator */
7889   freeAsmop (cond, NULL, ic, TRUE);
7890
7891   /* if there was something to be popped then do it */
7892   if (popIc)
7893     genIpop (popIc);
7894
7895   /* if the condition is  a bit variable */
7896   if (isbit && IS_ITEMP (cond) &&
7897       SPIL_LOC (cond))
7898     genIfxJump (ic, SPIL_LOC (cond)->rname);
7899   else if (isbit && !IS_ITEMP (cond))
7900     genIfxJump (ic, OP_SYMBOL (cond)->rname);
7901   else
7902     genIfxJump (ic, "a");
7903
7904   ic->generated = 1;
7905 }
7906
7907 /*-----------------------------------------------------------------*/
7908 /* genAddrOf - generates code for address of                       */
7909 /*-----------------------------------------------------------------*/
7910 static void
7911 genAddrOf (iCode * ic)
7912 {
7913   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7914   int size, offset;
7915
7916   aopOp (IC_RESULT (ic), ic, FALSE);
7917
7918   /* if the operand is on the stack then we
7919      need to get the stack offset of this
7920      variable */
7921   if (sym->onStack)
7922     {
7923       /* if it has an offset then we need to compute
7924          it */
7925       if (sym->stack)
7926         {
7927           emitcode ("mov", "a,_bp");
7928           emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
7929           aopPut (AOP (IC_RESULT (ic)), "a", 0);
7930         }
7931       else
7932         {
7933           /* we can just move _bp */
7934           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
7935         }
7936       /* fill the result with zero */
7937       size = AOP_SIZE (IC_RESULT (ic)) - 1;
7938
7939       offset = 1;
7940       while (size--)
7941         {
7942           aopPut (AOP (IC_RESULT (ic)), zero, offset++);
7943         }
7944
7945       goto release;
7946     }
7947
7948   /* object not on stack then we need the name */
7949   size = AOP_SIZE (IC_RESULT (ic));
7950   offset = 0;
7951
7952   while (size--)
7953     {
7954       char s[SDCC_NAME_MAX];
7955       if (offset)
7956         sprintf (s, "#(%s >> %d)",
7957                  sym->rname,
7958                  offset * 8);
7959       else
7960         sprintf (s, "#%s", sym->rname);
7961       aopPut (AOP (IC_RESULT (ic)), s, offset++);
7962     }
7963
7964 release:
7965   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7966
7967 }
7968
7969 /*-----------------------------------------------------------------*/
7970 /* genFarFarAssign - assignment when both are in far space         */
7971 /*-----------------------------------------------------------------*/
7972 static void
7973 genFarFarAssign (operand * result, operand * right, iCode * ic)
7974 {
7975   int size = AOP_SIZE (right);
7976   int offset = 0;
7977   char *l;
7978   /* first push the right side on to the stack */
7979   while (size--)
7980     {
7981       l = aopGet (AOP (right), offset++, FALSE, FALSE);
7982       MOVA (l);
7983       emitcode ("push", "acc");
7984     }
7985
7986   freeAsmop (right, NULL, ic, FALSE);
7987   /* now assign DPTR to result */
7988   aopOp (result, ic, FALSE);
7989   size = AOP_SIZE (result);
7990   while (size--)
7991     {
7992       emitcode ("pop", "acc");
7993       aopPut (AOP (result), "a", --offset);
7994     }
7995   freeAsmop (result, NULL, ic, FALSE);
7996
7997 }
7998
7999 /*-----------------------------------------------------------------*/
8000 /* genAssign - generate code for assignment                        */
8001 /*-----------------------------------------------------------------*/
8002 static void
8003 genAssign (iCode * ic)
8004 {
8005   operand *result, *right;
8006   int size, offset;
8007   unsigned long lit = 0L;
8008
8009   result = IC_RESULT (ic);
8010   right = IC_RIGHT (ic);
8011
8012   /* if they are the same */
8013   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8014     return;
8015
8016   aopOp (right, ic, FALSE);
8017
8018   /* special case both in far space */
8019   if (AOP_TYPE (right) == AOP_DPTR &&
8020       IS_TRUE_SYMOP (result) &&
8021       isOperandInFarSpace (result))
8022     {
8023
8024       genFarFarAssign (result, right, ic);
8025       return;
8026     }
8027
8028   aopOp (result, ic, TRUE);
8029
8030   /* if they are the same registers */
8031   if (sameRegs (AOP (right), AOP (result)))
8032     goto release;
8033
8034   /* if the result is a bit */
8035   if (AOP_TYPE (result) == AOP_CRY)
8036     {
8037
8038       /* if the right size is a literal then
8039          we know what the value is */
8040       if (AOP_TYPE (right) == AOP_LIT)
8041         {
8042           if (((int) operandLitValue (right)))
8043             aopPut (AOP (result), one, 0);
8044           else
8045             aopPut (AOP (result), zero, 0);
8046           goto release;
8047         }
8048
8049       /* the right is also a bit variable */
8050       if (AOP_TYPE (right) == AOP_CRY)
8051         {
8052           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8053           aopPut (AOP (result), "c", 0);
8054           goto release;
8055         }
8056
8057       /* we need to or */
8058       toBoolean (right);
8059       aopPut (AOP (result), "a", 0);
8060       goto release;
8061     }
8062
8063   /* bit variables done */
8064   /* general case */
8065   size = AOP_SIZE (result);
8066   offset = 0;
8067   if (AOP_TYPE (right) == AOP_LIT)
8068     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8069   if ((size > 1) &&
8070       (AOP_TYPE (result) != AOP_REG) &&
8071       (AOP_TYPE (right) == AOP_LIT) &&
8072       !IS_FLOAT (operandType (right)) &&
8073       (lit < 256L))
8074     {
8075       emitcode ("clr", "a");
8076       while (size--)
8077         {
8078           if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8079             aopPut (AOP (result), "a", size);
8080           else
8081             aopPut (AOP (result),
8082                     aopGet (AOP (right), size, FALSE, FALSE),
8083                     size);
8084         }
8085     }
8086   else
8087     {
8088       while (size--)
8089         {
8090           aopPut (AOP (result),
8091                   aopGet (AOP (right), offset, FALSE, FALSE),
8092                   offset);
8093           offset++;
8094         }
8095     }
8096
8097 release:
8098   freeAsmop (right, NULL, ic, TRUE);
8099   freeAsmop (result, NULL, ic, TRUE);
8100 }
8101
8102 /*-----------------------------------------------------------------*/
8103 /* genJumpTab - genrates code for jump table                       */
8104 /*-----------------------------------------------------------------*/
8105 static void
8106 genJumpTab (iCode * ic)
8107 {
8108   symbol *jtab;
8109   char *l;
8110
8111   aopOp (IC_JTCOND (ic), ic, FALSE);
8112   /* get the condition into accumulator */
8113   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8114   MOVA (l);
8115   /* multiply by three */
8116   emitcode ("add", "a,acc");
8117   emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8118   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8119
8120   jtab = newiTempLabel (NULL);
8121   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8122   emitcode ("jmp", "@a+dptr");
8123   emitcode ("", "%05d$:", jtab->key + 100);
8124   /* now generate the jump labels */
8125   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8126        jtab = setNextItem (IC_JTLABELS (ic)))
8127     emitcode ("ljmp", "%05d$", jtab->key + 100);
8128
8129 }
8130
8131 /*-----------------------------------------------------------------*/
8132 /* genCast - gen code for casting                                  */
8133 /*-----------------------------------------------------------------*/
8134 static void
8135 genCast (iCode * ic)
8136 {
8137   operand *result = IC_RESULT (ic);
8138   sym_link *ctype = operandType (IC_LEFT (ic));
8139   sym_link *rtype = operandType (IC_RIGHT (ic));
8140   operand *right = IC_RIGHT (ic);
8141   int size, offset;
8142
8143   /* if they are equivalent then do nothing */
8144   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8145     return;
8146
8147   aopOp (right, ic, FALSE);
8148   aopOp (result, ic, FALSE);
8149
8150   /* if the result is a bit */
8151   if (AOP_TYPE (result) == AOP_CRY)
8152     {
8153       /* if the right size is a literal then
8154          we know what the value is */
8155       if (AOP_TYPE (right) == AOP_LIT)
8156         {
8157           if (((int) operandLitValue (right)))
8158             aopPut (AOP (result), one, 0);
8159           else
8160             aopPut (AOP (result), zero, 0);
8161
8162           goto release;
8163         }
8164
8165       /* the right is also a bit variable */
8166       if (AOP_TYPE (right) == AOP_CRY)
8167         {
8168           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8169           aopPut (AOP (result), "c", 0);
8170           goto release;
8171         }
8172
8173       /* we need to or */
8174       toBoolean (right);
8175       aopPut (AOP (result), "a", 0);
8176       goto release;
8177     }
8178
8179   /* if they are the same size : or less */
8180   if (AOP_SIZE (result) <= AOP_SIZE (right))
8181     {
8182
8183       /* if they are in the same place */
8184       if (sameRegs (AOP (right), AOP (result)))
8185         goto release;
8186
8187       /* if they in different places then copy */
8188       size = AOP_SIZE (result);
8189       offset = 0;
8190       while (size--)
8191         {
8192           aopPut (AOP (result),
8193                   aopGet (AOP (right), offset, FALSE, FALSE),
8194                   offset);
8195           offset++;
8196         }
8197       goto release;
8198     }
8199
8200
8201   /* if the result is of type pointer */
8202   if (IS_PTR (ctype))
8203     {
8204
8205       int p_type;
8206       sym_link *type = operandType (right);
8207       sym_link *etype = getSpec (type);
8208
8209       /* pointer to generic pointer */
8210       if (IS_GENPTR (ctype))
8211         {
8212           char *l = zero;
8213
8214           if (IS_PTR (type))
8215             p_type = DCL_TYPE (type);
8216           else
8217             {
8218               if (SPEC_SCLS(etype)==S_REGISTER) {
8219                 // let's assume it is a generic pointer
8220                 p_type=GPOINTER;
8221               } else {
8222                 /* we have to go by the storage class */
8223                 p_type = PTR_TYPE (SPEC_OCLS (etype));
8224               }
8225             }
8226
8227           /* the first two bytes are known */
8228           size = GPTRSIZE - 1;
8229           offset = 0;
8230           while (size--)
8231             {
8232               aopPut (AOP (result),
8233                       aopGet (AOP (right), offset, FALSE, FALSE),
8234                       offset);
8235               offset++;
8236             }
8237           /* the last byte depending on type */
8238           switch (p_type)
8239             {
8240             case IPOINTER:
8241             case POINTER:
8242               l = zero;
8243               break;
8244             case FPOINTER:
8245               l = one;
8246               break;
8247             case CPOINTER:
8248               l = "#0x02";
8249               break;
8250             case GPOINTER:
8251               l = "0x03";
8252               break;
8253             case PPOINTER: // what the fck is this?
8254               l = "#0x03";
8255               break;
8256
8257             default:
8258               /* this should never happen */
8259               werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8260                       "got unknown pointer type");
8261               exit (1);
8262             }
8263           aopPut (AOP (result), l, GPTRSIZE - 1);
8264           goto release;
8265         }
8266
8267       /* just copy the pointers */
8268       size = AOP_SIZE (result);
8269       offset = 0;
8270       while (size--)
8271         {
8272           aopPut (AOP (result),
8273                   aopGet (AOP (right), offset, FALSE, FALSE),
8274                   offset);
8275           offset++;
8276         }
8277       goto release;
8278     }
8279
8280   /* so we now know that the size of destination is greater
8281      than the size of the source */
8282   /* we move to result for the size of source */
8283   size = AOP_SIZE (right);
8284   offset = 0;
8285   while (size--)
8286     {
8287       aopPut (AOP (result),
8288               aopGet (AOP (right), offset, FALSE, FALSE),
8289               offset);
8290       offset++;
8291     }
8292
8293   /* now depending on the sign of the source && destination */
8294   size = AOP_SIZE (result) - AOP_SIZE (right);
8295   /* if unsigned or not an integral type */
8296   if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
8297     {
8298       while (size--)
8299         aopPut (AOP (result), zero, offset++);
8300     }
8301   else
8302     {
8303       /* we need to extend the sign :{ */
8304       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8305                         FALSE, FALSE);
8306       MOVA (l);
8307       emitcode ("rlc", "a");
8308       emitcode ("subb", "a,acc");
8309       while (size--)
8310         aopPut (AOP (result), "a", offset++);
8311     }
8312
8313   /* we are done hurray !!!! */
8314
8315 release:
8316   freeAsmop (right, NULL, ic, TRUE);
8317   freeAsmop (result, NULL, ic, TRUE);
8318
8319 }
8320
8321 /*-----------------------------------------------------------------*/
8322 /* genDjnz - generate decrement & jump if not zero instrucion      */
8323 /*-----------------------------------------------------------------*/
8324 static int
8325 genDjnz (iCode * ic, iCode * ifx)
8326 {
8327   symbol *lbl, *lbl1;
8328   if (!ifx)
8329     return 0;
8330
8331   /* if the if condition has a false label
8332      then we cannot save */
8333   if (IC_FALSE (ifx))
8334     return 0;
8335
8336   /* if the minus is not of the form
8337      a = a - 1 */
8338   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8339       !IS_OP_LITERAL (IC_RIGHT (ic)))
8340     return 0;
8341
8342   if (operandLitValue (IC_RIGHT (ic)) != 1)
8343     return 0;
8344
8345   /* if the size of this greater than one then no
8346      saving */
8347   if (getSize (operandType (IC_RESULT (ic))) > 1)
8348     return 0;
8349
8350   /* otherwise we can save BIG */
8351   lbl = newiTempLabel (NULL);
8352   lbl1 = newiTempLabel (NULL);
8353
8354   aopOp (IC_RESULT (ic), ic, FALSE);
8355
8356   if (AOP_NEEDSACC(IC_RESULT(ic)))
8357   {
8358       /* If the result is accessed indirectly via
8359        * the accumulator, we must explicitly write
8360        * it back after the decrement.
8361        */
8362       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8363       
8364       if (strcmp(rByte, "a"))
8365       {
8366            /* Something is hopelessly wrong */
8367            fprintf(stderr, "*** warning: internal error at %s:%d\n",
8368                    __FILE__, __LINE__);
8369            /* We can just give up; the generated code will be inefficient,
8370             * but what the hey.
8371             */
8372            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8373            return 0;
8374       }
8375       emitcode ("dec", "%s", rByte);
8376       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8377       emitcode ("jnz", "%05d$", lbl->key + 100);
8378   }
8379   else if (IS_AOP_PREG (IC_RESULT (ic)))
8380     {
8381       emitcode ("dec", "%s",
8382                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8383       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8384       emitcode ("jnz", "%05d$", lbl->key + 100);
8385     }
8386   else
8387     {
8388       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8389                 lbl->key + 100);
8390     }
8391   emitcode ("sjmp", "%05d$", lbl1->key + 100);
8392   emitcode ("", "%05d$:", lbl->key + 100);
8393   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8394   emitcode ("", "%05d$:", lbl1->key + 100);
8395
8396   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8397   ifx->generated = 1;
8398   return 1;
8399 }
8400
8401 /*-----------------------------------------------------------------*/
8402 /* genReceive - generate code for a receive iCode                  */
8403 /*-----------------------------------------------------------------*/
8404 static void
8405 genReceive (iCode * ic)
8406 {
8407   if (isOperandInFarSpace (IC_RESULT (ic)) &&
8408       (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8409        IS_TRUE_SYMOP (IC_RESULT (ic))))
8410     {
8411
8412       int size = getSize (operandType (IC_RESULT (ic)));
8413       int offset = fReturnSizeMCS51 - size;
8414       while (size--)
8415         {
8416           emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8417                                 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8418           offset++;
8419         }
8420       aopOp (IC_RESULT (ic), ic, FALSE);
8421       size = AOP_SIZE (IC_RESULT (ic));
8422       offset = 0;
8423       while (size--)
8424         {
8425           emitcode ("pop", "acc");
8426           aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8427         }
8428
8429     }
8430   else
8431     {
8432       _G.accInUse++;
8433       aopOp (IC_RESULT (ic), ic, FALSE);
8434       _G.accInUse--;
8435       assignResultValue (IC_RESULT (ic));
8436     }
8437
8438   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8439 }
8440
8441 /*-----------------------------------------------------------------*/
8442 /* gen51Code - generate code for 8051 based controllers            */
8443 /*-----------------------------------------------------------------*/
8444 void
8445 gen51Code (iCode * lic)
8446 {
8447   iCode *ic;
8448   int cln = 0;
8449
8450   lineHead = lineCurr = NULL;
8451
8452   /* print the allocation information */
8453   if (allocInfo)
8454     printAllocInfo (currFunc, codeOutFile);
8455   /* if debug information required */
8456   /*     if (options.debug && currFunc) { */
8457   if (options.debug && currFunc)
8458     {
8459       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8460       _G.debugLine = 1;
8461       if (IS_STATIC (currFunc->etype))
8462         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8463       else
8464         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8465       _G.debugLine = 0;
8466     }
8467   /* stack pointer name */
8468   if (options.useXstack)
8469     spname = "_spx";
8470   else
8471     spname = "sp";
8472
8473
8474   for (ic = lic; ic; ic = ic->next)
8475     {
8476
8477       if (cln != ic->lineno)
8478         {
8479           if (options.debug)
8480             {
8481               _G.debugLine = 1;
8482               emitcode ("", "C$%s$%d$%d$%d ==.",
8483                         FileBaseName (ic->filename), ic->lineno,
8484                         ic->level, ic->block);
8485               _G.debugLine = 0;
8486             }
8487           emitcode (";", "%s %d", ic->filename, ic->lineno);
8488           cln = ic->lineno;
8489         }
8490       /* if the result is marked as
8491          spilt and rematerializable or code for
8492          this has already been generated then
8493          do nothing */
8494       if (resultRemat (ic) || ic->generated)
8495         continue;
8496
8497       /* depending on the operation */
8498       switch (ic->op)
8499         {
8500         case '!':
8501           genNot (ic);
8502           break;
8503
8504         case '~':
8505           genCpl (ic);
8506           break;
8507
8508         case UNARYMINUS:
8509           genUminus (ic);
8510           break;
8511
8512         case IPUSH:
8513           genIpush (ic);
8514           break;
8515
8516         case IPOP:
8517           /* IPOP happens only when trying to restore a
8518              spilt live range, if there is an ifx statement
8519              following this pop then the if statement might
8520              be using some of the registers being popped which
8521              would destory the contents of the register so
8522              we need to check for this condition and handle it */
8523           if (ic->next &&
8524               ic->next->op == IFX &&
8525               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8526             genIfx (ic->next, ic);
8527           else
8528             genIpop (ic);
8529           break;
8530
8531         case CALL:
8532           genCall (ic);
8533           break;
8534
8535         case PCALL:
8536           genPcall (ic);
8537           break;
8538
8539         case FUNCTION:
8540           genFunction (ic);
8541           break;
8542
8543         case ENDFUNCTION:
8544           genEndFunction (ic);
8545           break;
8546
8547         case RETURN:
8548           genRet (ic);
8549           break;
8550
8551         case LABEL:
8552           genLabel (ic);
8553           break;
8554
8555         case GOTO:
8556           genGoto (ic);
8557           break;
8558
8559         case '+':
8560           genPlus (ic);
8561           break;
8562
8563         case '-':
8564           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8565             genMinus (ic);
8566           break;
8567
8568         case '*':
8569           genMult (ic);
8570           break;
8571
8572         case '/':
8573           genDiv (ic);
8574           break;
8575
8576         case '%':
8577           genMod (ic);
8578           break;
8579
8580         case '>':
8581           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8582           break;
8583
8584         case '<':
8585           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8586           break;
8587
8588         case LE_OP:
8589         case GE_OP:
8590         case NE_OP:
8591
8592           /* note these two are xlated by algebraic equivalence
8593              during parsing SDCC.y */
8594           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8595                   "got '>=' or '<=' shouldn't have come here");
8596           break;
8597
8598         case EQ_OP:
8599           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8600           break;
8601
8602         case AND_OP:
8603           genAndOp (ic);
8604           break;
8605
8606         case OR_OP:
8607           genOrOp (ic);
8608           break;
8609
8610         case '^':
8611           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8612           break;
8613
8614         case '|':
8615           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8616           break;
8617
8618         case BITWISEAND:
8619           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8620           break;
8621
8622         case INLINEASM:
8623           genInline (ic);
8624           break;
8625
8626         case RRC:
8627           genRRC (ic);
8628           break;
8629
8630         case RLC:
8631           genRLC (ic);
8632           break;
8633
8634         case GETHBIT:
8635           genGetHbit (ic);
8636           break;
8637
8638         case LEFT_OP:
8639           genLeftShift (ic);
8640           break;
8641
8642         case RIGHT_OP:
8643           genRightShift (ic);
8644           break;
8645
8646         case GET_VALUE_AT_ADDRESS:
8647           genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8648           break;
8649
8650         case '=':
8651           if (POINTER_SET (ic))
8652             genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8653           else
8654             genAssign (ic);
8655           break;
8656
8657         case IFX:
8658           genIfx (ic, NULL);
8659           break;
8660
8661         case ADDRESS_OF:
8662           genAddrOf (ic);
8663           break;
8664
8665         case JUMPTABLE:
8666           genJumpTab (ic);
8667           break;
8668
8669         case CAST:
8670           genCast (ic);
8671           break;
8672
8673         case RECEIVE:
8674           genReceive (ic);
8675           break;
8676
8677         case SEND:
8678           addSet (&_G.sendSet, ic);
8679           break;
8680
8681         default:
8682           ic = ic;
8683         }
8684     }
8685
8686
8687   /* now we are ready to call the
8688      peep hole optimizer */
8689   if (!options.nopeep)
8690     peepHole (&lineHead);
8691
8692   /* now do the actual printing */
8693   printLine (lineHead, codeOutFile);
8694   return;
8695 }