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