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