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