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