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