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