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