5c7693f79505116e985aa7b5f67e03e909bf1ded
[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           if (pi)
7526             {
7527               emitcode ("clr", "a");
7528               emitcode ("movc", "a,@a+dptr");
7529               aopPut (AOP (result), "a", offset++);
7530               emitcode ("inc", "dptr");
7531             }
7532           else
7533             { 
7534               emitcode ("mov", "a,#0x%02x", offset);
7535               emitcode ("movc", "a,@a+dptr");
7536               aopPut (AOP (result), "a", offset++);
7537             }
7538         }
7539     }
7540
7541   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7542     aopPut ( AOP (left), "dpl", 0);
7543     aopPut ( AOP (left), "dph", 1);
7544     pi->generated = 1;
7545   }
7546   freeAsmop (left, NULL, ic, TRUE);
7547   freeAsmop (result, NULL, ic, TRUE);
7548 }
7549
7550 /*-----------------------------------------------------------------*/
7551 /* genGenPointerGet - gget value from generic pointer space        */
7552 /*-----------------------------------------------------------------*/
7553 static void
7554 genGenPointerGet (operand * left,
7555                   operand * result, iCode * ic, iCode *pi)
7556 {
7557   int size, offset;
7558   sym_link *retype = getSpec (operandType (result));
7559
7560   D(emitcode (";     genGenPointerGet",""));
7561
7562   aopOp (left, ic, FALSE);
7563
7564   /* if the operand is already in dptr
7565      then we do nothing else we move the value to dptr */
7566   if (AOP_TYPE (left) != AOP_STR)
7567     {
7568       /* if this is remateriazable */
7569       if (AOP_TYPE (left) == AOP_IMMD)
7570         {
7571           emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7572           if (AOP(left)->aopu.aop_immd.from_cast_remat) 
7573                   emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7574           else
7575                   emitcode ("mov", "b,#%d", pointerCode (retype));
7576         }
7577       else
7578         {                       /* we need to get it byte by byte */
7579           emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7580           emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7581           emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7582         }
7583     }
7584   /* so dptr know contains the address */
7585   aopOp (result, ic, FALSE);
7586
7587   /* if bit then unpack */
7588   if (IS_BITVAR (retype))
7589     genUnpackBits (result, "dptr", GPOINTER);
7590   else
7591     {
7592       size = AOP_SIZE (result);
7593       offset = 0;
7594
7595       while (size--)
7596         {
7597           emitcode ("lcall", "__gptrget");
7598           aopPut (AOP (result), "a", offset++);
7599           if (size || pi)
7600             emitcode ("inc", "dptr");
7601         }
7602     }
7603
7604   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7605     aopPut ( AOP (left), "dpl", 0);
7606     aopPut ( AOP (left), "dph", 1);
7607     aopPut ( AOP (left), "b", 2);
7608     pi->generated = 1;
7609   }
7610   freeAsmop (left, NULL, ic, TRUE);
7611   freeAsmop (result, NULL, ic, TRUE);
7612 }
7613
7614 /*-----------------------------------------------------------------*/
7615 /* genPointerGet - generate code for pointer get                   */
7616 /*-----------------------------------------------------------------*/
7617 static void
7618 genPointerGet (iCode * ic, iCode *pi)
7619 {
7620   operand *left, *result;
7621   sym_link *type, *etype;
7622   int p_type;
7623
7624   D(emitcode (";     genPointerGet",""));
7625
7626   left = IC_LEFT (ic);
7627   result = IC_RESULT (ic);
7628
7629   /* depending on the type of pointer we need to
7630      move it to the correct pointer register */
7631   type = operandType (left);
7632   etype = getSpec (type);
7633   /* if left is of type of pointer then it is simple */
7634   if (IS_PTR (type) && !IS_FUNC (type->next))
7635     p_type = DCL_TYPE (type);
7636   else
7637     {
7638       /* we have to go by the storage class */
7639       p_type = PTR_TYPE (SPEC_OCLS (etype));
7640     }
7641
7642   /* special case when cast remat */
7643   if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7644       IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7645           left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7646           type = operandType (left);
7647           p_type = DCL_TYPE (type);
7648   }
7649   /* now that we have the pointer type we assign
7650      the pointer values */
7651   switch (p_type)
7652     {
7653
7654     case POINTER:
7655     case IPOINTER:
7656       genNearPointerGet (left, result, ic, pi);
7657       break;
7658
7659     case PPOINTER:
7660       genPagedPointerGet (left, result, ic, pi);
7661       break;
7662
7663     case FPOINTER:
7664       genFarPointerGet (left, result, ic, pi);
7665       break;
7666
7667     case CPOINTER:
7668       genCodePointerGet (left, result, ic, pi);
7669       break;
7670
7671     case GPOINTER:
7672       genGenPointerGet (left, result, ic, pi);
7673       break;
7674     }
7675
7676 }
7677
7678 /*-----------------------------------------------------------------*/
7679 /* genPackBits - generates code for packed bit storage             */
7680 /*-----------------------------------------------------------------*/
7681 static void
7682 genPackBits (sym_link * etype,
7683              operand * right,
7684              char *rname, int p_type)
7685 {
7686   int shCount = 0;
7687   int offset = 0;
7688   int rLen = 0;
7689   int blen, bstr;
7690   char *l;
7691
7692   D(emitcode (";     genPackBits",""));
7693
7694   blen = SPEC_BLEN (etype);
7695   bstr = SPEC_BSTR (etype);
7696
7697   l = aopGet (AOP (right), offset++, FALSE, FALSE);
7698   MOVA (l);
7699
7700   /* if the bit lenth is less than or    */
7701   /* it exactly fits a byte then         */
7702   if (SPEC_BLEN (etype) <= 8)
7703     {
7704       shCount = SPEC_BSTR (etype);
7705
7706       /* shift left acc */
7707       AccLsh (shCount);
7708
7709       if (SPEC_BLEN (etype) < 8)
7710         {                       /* if smaller than a byte */
7711
7712
7713           switch (p_type)
7714             {
7715             case POINTER:
7716               emitcode ("mov", "b,a");
7717               emitcode ("mov", "a,@%s", rname);
7718               break;
7719
7720             case FPOINTER:
7721               emitcode ("mov", "b,a");
7722               emitcode ("movx", "a,@dptr");
7723               break;
7724
7725             case GPOINTER:
7726               emitcode ("push", "b");
7727               emitcode ("push", "acc");
7728               emitcode ("lcall", "__gptrget");
7729               emitcode ("pop", "b");
7730               break;
7731             }
7732
7733           emitcode ("anl", "a,#0x%02x", (unsigned char)
7734                     ((unsigned char) (0xFF << (blen + bstr)) |
7735                      (unsigned char) (0xFF >> (8 - bstr))));
7736           emitcode ("orl", "a,b");
7737           if (p_type == GPOINTER)
7738             emitcode ("pop", "b");
7739         }
7740     }
7741
7742   switch (p_type)
7743     {
7744     case POINTER:
7745       emitcode ("mov", "@%s,a", rname);
7746       break;
7747
7748     case FPOINTER:
7749       emitcode ("movx", "@dptr,a");
7750       break;
7751
7752     case GPOINTER:
7753       emitcode ("lcall", "__gptrput");
7754       break;
7755     }
7756
7757   /* if we r done */
7758   if (SPEC_BLEN (etype) <= 8)
7759     return;
7760
7761   emitcode ("inc", "%s", rname);
7762   rLen = SPEC_BLEN (etype);
7763
7764   /* now generate for lengths greater than one byte */
7765   while (1)
7766     {
7767
7768       l = aopGet (AOP (right), offset++, FALSE, TRUE);
7769
7770       rLen -= 8;
7771       if (rLen < 8)
7772         break;
7773
7774       switch (p_type)
7775         {
7776         case POINTER:
7777           if (*l == '@')
7778             {
7779               MOVA (l);
7780               emitcode ("mov", "@%s,a", rname);
7781             }
7782           else
7783             emitcode ("mov", "@%s,%s", rname, l);
7784           break;
7785
7786         case FPOINTER:
7787           MOVA (l);
7788           emitcode ("movx", "@dptr,a");
7789           break;
7790
7791         case GPOINTER:
7792           MOVA (l);
7793           emitcode ("lcall", "__gptrput");
7794           break;
7795         }
7796       emitcode ("inc", "%s", rname);
7797     }
7798
7799   MOVA (l);
7800
7801   /* last last was not complete */
7802   if (rLen)
7803     {
7804       /* save the byte & read byte */
7805       switch (p_type)
7806         {
7807         case POINTER:
7808           emitcode ("mov", "b,a");
7809           emitcode ("mov", "a,@%s", rname);
7810           break;
7811
7812         case FPOINTER:
7813           emitcode ("mov", "b,a");
7814           emitcode ("movx", "a,@dptr");
7815           break;
7816
7817         case GPOINTER:
7818           emitcode ("push", "b");
7819           emitcode ("push", "acc");
7820           emitcode ("lcall", "__gptrget");
7821           emitcode ("pop", "b");
7822           break;
7823         }
7824
7825       emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7826       emitcode ("orl", "a,b");
7827     }
7828
7829   if (p_type == GPOINTER)
7830     emitcode ("pop", "b");
7831
7832   switch (p_type)
7833     {
7834
7835     case POINTER:
7836       emitcode ("mov", "@%s,a", rname);
7837       break;
7838
7839     case FPOINTER:
7840       emitcode ("movx", "@dptr,a");
7841       break;
7842
7843     case GPOINTER:
7844       emitcode ("lcall", "__gptrput");
7845       break;
7846     }
7847 }
7848 /*-----------------------------------------------------------------*/
7849 /* genDataPointerSet - remat pointer to data space                 */
7850 /*-----------------------------------------------------------------*/
7851 static void
7852 genDataPointerSet (operand * right,
7853                    operand * result,
7854                    iCode * ic)
7855 {
7856   int size, offset = 0;
7857   char *l, buffer[256];
7858
7859   D(emitcode (";     genDataPointerSet",""));
7860
7861   aopOp (right, ic, FALSE);
7862
7863   l = aopGet (AOP (result), 0, FALSE, TRUE);
7864   size = AOP_SIZE (right);
7865   while (size--)
7866     {
7867       if (offset)
7868         sprintf (buffer, "(%s + %d)", l + 1, offset);
7869       else
7870         sprintf (buffer, "%s", l + 1);
7871       emitcode ("mov", "%s,%s", buffer,
7872                 aopGet (AOP (right), offset++, FALSE, FALSE));
7873     }
7874
7875   freeAsmop (right, NULL, ic, TRUE);
7876   freeAsmop (result, NULL, ic, TRUE);
7877 }
7878
7879 /*-----------------------------------------------------------------*/
7880 /* genNearPointerSet - emitcode for near pointer put                */
7881 /*-----------------------------------------------------------------*/
7882 static void
7883 genNearPointerSet (operand * right,
7884                    operand * result,
7885                    iCode * ic,
7886                    iCode * pi)
7887 {
7888   asmop *aop = NULL;
7889   regs *preg = NULL;
7890   char *rname, *l;
7891   sym_link *retype, *letype;
7892   sym_link *ptype = operandType (result);
7893
7894   D(emitcode (";     genNearPointerSet",""));
7895
7896   retype = getSpec (operandType (right));
7897   letype = getSpec (ptype);
7898   aopOp (result, ic, FALSE);
7899
7900   /* if the result is rematerializable &
7901      in data space & not a bit variable */
7902   if (AOP_TYPE (result) == AOP_IMMD &&
7903       DCL_TYPE (ptype) == POINTER &&
7904       !IS_BITVAR (retype) &&
7905       !IS_BITVAR (letype))
7906     {
7907       genDataPointerSet (right, result, ic);
7908       return;
7909     }
7910   
7911   /* if the value is already in a pointer register
7912      then don't need anything more */
7913   if (!AOP_INPREG (AOP (result)))
7914     {
7915         if (
7916             //AOP_TYPE (result) == AOP_STK
7917             IS_AOP_PREG(result)
7918             )
7919         {
7920             // Aha, it is a pointer, just in disguise.
7921             rname = aopGet (AOP (result), 0, FALSE, FALSE);
7922             if (*rname != '@')
7923             {
7924                 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7925                         __FILE__, __LINE__);
7926             }
7927             else
7928             {
7929                 // Expected case.
7930                 rname++;  // skip the '@'.
7931             }
7932         }
7933         else
7934         {
7935             /* otherwise get a free pointer register */
7936             aop = newAsmop (0);
7937             preg = getFreePtr (ic, &aop, FALSE);
7938             emitcode ("mov", "%s,%s",
7939                       preg->name,
7940                       aopGet (AOP (result), 0, FALSE, TRUE));
7941             rname = preg->name;
7942         }
7943     }
7944     else
7945     {
7946         rname = aopGet (AOP (result), 0, FALSE, FALSE);
7947     }
7948
7949   aopOp (right, ic, FALSE);
7950     
7951   /* if bitfield then unpack the bits */
7952   if (IS_BITVAR (retype) || IS_BITVAR (letype))
7953     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7954   else
7955     {
7956       /* we have can just get the values */
7957       int size = AOP_SIZE (right);
7958       int offset = 0;
7959
7960       while (size--)
7961         {
7962           l = aopGet (AOP (right), offset, FALSE, TRUE);
7963           if (*l == '@')
7964             {
7965               MOVA (l);
7966               emitcode ("mov", "@%s,a", rname);
7967             }
7968           else
7969             emitcode ("mov", "@%s,%s", rname, l);
7970           if (size || pi)
7971             emitcode ("inc", "%s", rname);
7972           offset++;
7973         }
7974     }
7975
7976   /* now some housekeeping stuff */
7977   if (aop) /* we had to allocate for this iCode */
7978     {
7979       if (pi) aopPut (AOP (result),rname,0);
7980       freeAsmop (NULL, aop, ic, TRUE);
7981     }
7982   else
7983     {
7984       /* we did not allocate which means left
7985          already in a pointer register, then
7986          if size > 0 && this could be used again
7987          we have to point it back to where it
7988          belongs */
7989       if ((AOP_SIZE (right) > 1 &&
7990            !OP_SYMBOL (result)->remat &&
7991            (OP_SYMBOL (result)->liveTo > ic->seq ||
7992             ic->depth)) &&
7993           !pi)
7994         {
7995           int size = AOP_SIZE (right) - 1;
7996           while (size--)
7997             emitcode ("dec", "%s", rname);
7998         }
7999     }
8000
8001   /* done */
8002   if (pi) pi->generated = 1;
8003   freeAsmop (result, NULL, ic, TRUE);
8004   freeAsmop (right, NULL, ic, TRUE);
8005 }
8006
8007 /*-----------------------------------------------------------------*/
8008 /* genPagedPointerSet - emitcode for Paged pointer put             */
8009 /*-----------------------------------------------------------------*/
8010 static void
8011 genPagedPointerSet (operand * right,
8012                     operand * result,
8013                     iCode * ic,
8014                     iCode * pi)
8015 {
8016   asmop *aop = NULL;
8017   regs *preg = NULL;
8018   char *rname, *l;
8019   sym_link *retype, *letype;
8020
8021   D(emitcode (";     genPagedPointerSet",""));
8022
8023   retype = getSpec (operandType (right));
8024   letype = getSpec (operandType (result));
8025
8026   aopOp (result, ic, FALSE);
8027
8028   /* if the value is already in a pointer register
8029      then don't need anything more */
8030   if (!AOP_INPREG (AOP (result)))
8031     {
8032       /* otherwise get a free pointer register */
8033       aop = newAsmop (0);
8034       preg = getFreePtr (ic, &aop, FALSE);
8035       emitcode ("mov", "%s,%s",
8036                 preg->name,
8037                 aopGet (AOP (result), 0, FALSE, TRUE));
8038       rname = preg->name;
8039     }
8040   else
8041     rname = aopGet (AOP (result), 0, FALSE, FALSE);
8042
8043   aopOp (right, ic, FALSE);
8044
8045   /* if bitfield then unpack the bits */
8046   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8047     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8048   else
8049     {
8050       /* we have can just get the values */
8051       int size = AOP_SIZE (right);
8052       int offset = 0;
8053
8054       while (size--)
8055         {
8056           l = aopGet (AOP (right), offset, FALSE, TRUE);
8057
8058           MOVA (l);
8059           emitcode ("movx", "@%s,a", rname);
8060
8061           if (size || pi)
8062             emitcode ("inc", "%s", rname);
8063
8064           offset++;
8065         }
8066     }
8067
8068   /* now some housekeeping stuff */
8069   if (aop) /* we had to allocate for this iCode */
8070     {
8071       if (pi) aopPut (AOP (result),rname,0);
8072       freeAsmop (NULL, aop, ic, TRUE);
8073     }
8074   else
8075     {
8076       /* we did not allocate which means left
8077          already in a pointer register, then
8078          if size > 0 && this could be used again
8079          we have to point it back to where it
8080          belongs */
8081       if (AOP_SIZE (right) > 1 &&
8082           !OP_SYMBOL (result)->remat &&
8083           (OP_SYMBOL (result)->liveTo > ic->seq ||
8084            ic->depth))
8085         {
8086           int size = AOP_SIZE (right) - 1;
8087           while (size--)
8088             emitcode ("dec", "%s", rname);
8089         }
8090     }
8091
8092   /* done */
8093   if (pi) pi->generated = 1;
8094   freeAsmop (result, NULL, ic, TRUE);
8095   freeAsmop (right, NULL, ic, TRUE);
8096
8097
8098 }
8099
8100 /*-----------------------------------------------------------------*/
8101 /* genFarPointerSet - set value from far space                     */
8102 /*-----------------------------------------------------------------*/
8103 static void
8104 genFarPointerSet (operand * right,
8105                   operand * result, iCode * ic, iCode * pi)
8106 {
8107   int size, offset;
8108   sym_link *retype = getSpec (operandType (right));
8109   sym_link *letype = getSpec (operandType (result));
8110
8111   D(emitcode (";     genFarPointerSet",""));
8112
8113   aopOp (result, ic, FALSE);
8114
8115   /* if the operand is already in dptr
8116      then we do nothing else we move the value to dptr */
8117   if (AOP_TYPE (result) != AOP_STR)
8118     {
8119       /* if this is remateriazable */
8120       if (AOP_TYPE (result) == AOP_IMMD)
8121         emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8122       else
8123         {                       /* we need to get it byte by byte */
8124           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8125           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8126         }
8127     }
8128   /* so dptr know contains the address */
8129   aopOp (right, ic, FALSE);
8130
8131   /* if bit then unpack */
8132   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8133     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8134   else
8135     {
8136       size = AOP_SIZE (right);
8137       offset = 0;
8138
8139       while (size--)
8140         {
8141           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8142           MOVA (l);
8143           emitcode ("movx", "@dptr,a");
8144           if (size || pi)
8145             emitcode ("inc", "dptr");
8146         }
8147     }
8148   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8149     aopPut (AOP(result),"dpl",0);
8150     aopPut (AOP(result),"dph",1);
8151     pi->generated=1;
8152   }
8153   freeAsmop (result, NULL, ic, TRUE);
8154   freeAsmop (right, NULL, ic, TRUE);
8155 }
8156
8157 /*-----------------------------------------------------------------*/
8158 /* genGenPointerSet - set value from generic pointer space         */
8159 /*-----------------------------------------------------------------*/
8160 static void
8161 genGenPointerSet (operand * right,
8162                   operand * result, iCode * ic, iCode * pi)
8163 {
8164   int size, offset;
8165   sym_link *retype = getSpec (operandType (right));
8166   sym_link *letype = getSpec (operandType (result));
8167
8168   D(emitcode (";     genGenPointerSet",""));
8169
8170   aopOp (result, ic, FALSE);
8171
8172   /* if the operand is already in dptr
8173      then we do nothing else we move the value to dptr */
8174   if (AOP_TYPE (result) != AOP_STR)
8175     {
8176       /* if this is remateriazable */
8177       if (AOP_TYPE (result) == AOP_IMMD)
8178         {
8179           emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8180           if (AOP(result)->aopu.aop_immd.from_cast_remat) 
8181                   emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8182           else 
8183                   emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8184         }
8185       else
8186         {                       /* we need to get it byte by byte */
8187           emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8188           emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8189           emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8190         }
8191     }
8192   /* so dptr know contains the address */
8193   aopOp (right, ic, FALSE);
8194
8195   /* if bit then unpack */
8196   if (IS_BITVAR (retype) || IS_BITVAR (letype))
8197     genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8198   else
8199     {
8200       size = AOP_SIZE (right);
8201       offset = 0;
8202
8203       while (size--)
8204         {
8205           char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8206           MOVA (l);
8207           emitcode ("lcall", "__gptrput");
8208           if (size || pi)
8209             emitcode ("inc", "dptr");
8210         }
8211     }
8212
8213   if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8214     aopPut (AOP(result),"dpl",0);
8215     aopPut (AOP(result),"dph",1);
8216     aopPut (AOP(result),"b",2);
8217     pi->generated=1;
8218   }
8219   freeAsmop (result, NULL, ic, TRUE);
8220   freeAsmop (right, NULL, ic, TRUE);
8221 }
8222
8223 /*-----------------------------------------------------------------*/
8224 /* genPointerSet - stores the value into a pointer location        */
8225 /*-----------------------------------------------------------------*/
8226 static void
8227 genPointerSet (iCode * ic, iCode *pi)
8228 {
8229   operand *right, *result;
8230   sym_link *type, *etype;
8231   int p_type;
8232
8233   D(emitcode (";     genPointerSet",""));
8234
8235   right = IC_RIGHT (ic);
8236   result = IC_RESULT (ic);
8237
8238   /* depending on the type of pointer we need to
8239      move it to the correct pointer register */
8240   type = operandType (result);
8241   etype = getSpec (type);
8242   /* if left is of type of pointer then it is simple */
8243   if (IS_PTR (type) && !IS_FUNC (type->next))
8244     {
8245       p_type = DCL_TYPE (type);
8246     }
8247   else
8248     {
8249       /* we have to go by the storage class */
8250       p_type = PTR_TYPE (SPEC_OCLS (etype));
8251     }
8252
8253   /* special case when cast remat */
8254   if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8255       IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8256           result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8257           type = operandType (result);
8258           p_type = DCL_TYPE (type);
8259   }
8260   /* now that we have the pointer type we assign
8261      the pointer values */
8262   switch (p_type)
8263     {
8264
8265     case POINTER:
8266     case IPOINTER:
8267       genNearPointerSet (right, result, ic, pi);
8268       break;
8269
8270     case PPOINTER:
8271       genPagedPointerSet (right, result, ic, pi);
8272       break;
8273
8274     case FPOINTER:
8275       genFarPointerSet (right, result, ic, pi);
8276       break;
8277
8278     case GPOINTER:
8279       genGenPointerSet (right, result, ic, pi);
8280       break;
8281
8282     default:
8283       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
8284               "genPointerSet: illegal pointer type");
8285     }
8286
8287 }
8288
8289 /*-----------------------------------------------------------------*/
8290 /* genIfx - generate code for Ifx statement                        */
8291 /*-----------------------------------------------------------------*/
8292 static void
8293 genIfx (iCode * ic, iCode * popIc)
8294 {
8295   operand *cond = IC_COND (ic);
8296   int isbit = 0;
8297
8298   D(emitcode (";     genIfx",""));
8299
8300   aopOp (cond, ic, FALSE);
8301
8302   /* get the value into acc */
8303   if (AOP_TYPE (cond) != AOP_CRY)
8304     toBoolean (cond);
8305   else
8306     isbit = 1;
8307   /* the result is now in the accumulator */
8308   freeAsmop (cond, NULL, ic, TRUE);
8309
8310   /* if there was something to be popped then do it */
8311   if (popIc)
8312     genIpop (popIc);
8313
8314   /* if the condition is  a bit variable */
8315   if (isbit && IS_ITEMP (cond) &&
8316       SPIL_LOC (cond))
8317     genIfxJump (ic, SPIL_LOC (cond)->rname);
8318   else if (isbit && !IS_ITEMP (cond))
8319     genIfxJump (ic, OP_SYMBOL (cond)->rname);
8320   else
8321     genIfxJump (ic, "a");
8322
8323   ic->generated = 1;
8324 }
8325
8326 /*-----------------------------------------------------------------*/
8327 /* genAddrOf - generates code for address of                       */
8328 /*-----------------------------------------------------------------*/
8329 static void
8330 genAddrOf (iCode * ic)
8331 {
8332   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8333   int size, offset;
8334
8335   D(emitcode (";     genAddrOf",""));
8336
8337   aopOp (IC_RESULT (ic), ic, FALSE);
8338
8339   /* if the operand is on the stack then we
8340      need to get the stack offset of this
8341      variable */
8342   if (sym->onStack)
8343     {
8344       /* if it has an offset then we need to compute
8345          it */
8346       if (sym->stack)
8347         {
8348           emitcode ("mov", "a,_bp");
8349           emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8350                                          ((char) (sym->stack - _G.nRegsSaved)) :
8351                                          ((char) sym->stack)) & 0xff);
8352           aopPut (AOP (IC_RESULT (ic)), "a", 0);
8353         }
8354       else
8355         {
8356           /* we can just move _bp */
8357           aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8358         }
8359       /* fill the result with zero */
8360       size = AOP_SIZE (IC_RESULT (ic)) - 1;
8361
8362       offset = 1;
8363       while (size--)
8364         {
8365           aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8366         }
8367
8368       goto release;
8369     }
8370
8371   /* object not on stack then we need the name */
8372   size = AOP_SIZE (IC_RESULT (ic));
8373   offset = 0;
8374
8375   while (size--)
8376     {
8377       char s[SDCC_NAME_MAX];
8378       if (offset)
8379         sprintf (s, "#(%s >> %d)",
8380                  sym->rname,
8381                  offset * 8);
8382       else
8383         sprintf (s, "#%s", sym->rname);
8384       aopPut (AOP (IC_RESULT (ic)), s, offset++);
8385     }
8386
8387 release:
8388   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8389
8390 }
8391
8392 /*-----------------------------------------------------------------*/
8393 /* genFarFarAssign - assignment when both are in far space         */
8394 /*-----------------------------------------------------------------*/
8395 static void
8396 genFarFarAssign (operand * result, operand * right, iCode * ic)
8397 {
8398   int size = AOP_SIZE (right);
8399   int offset = 0;
8400   char *l;
8401
8402   D(emitcode (";     genFarFarAssign",""));
8403
8404   /* first push the right side on to the stack */
8405   while (size--)
8406     {
8407       l = aopGet (AOP (right), offset++, FALSE, FALSE);
8408       MOVA (l);
8409       emitcode ("push", "acc");
8410     }
8411
8412   freeAsmop (right, NULL, ic, FALSE);
8413   /* now assign DPTR to result */
8414   aopOp (result, ic, FALSE);
8415   size = AOP_SIZE (result);
8416   while (size--)
8417     {
8418       emitcode ("pop", "acc");
8419       aopPut (AOP (result), "a", --offset);
8420     }
8421   freeAsmop (result, NULL, ic, FALSE);
8422
8423 }
8424
8425 /*-----------------------------------------------------------------*/
8426 /* genAssign - generate code for assignment                        */
8427 /*-----------------------------------------------------------------*/
8428 static void
8429 genAssign (iCode * ic)
8430 {
8431   operand *result, *right;
8432   int size, offset;
8433   unsigned long lit = 0L;
8434
8435   D(emitcode(";     genAssign",""));
8436
8437   result = IC_RESULT (ic);
8438   right = IC_RIGHT (ic);
8439
8440   /* if they are the same */
8441   if (operandsEqu (result, right)) {
8442     return;
8443   }
8444
8445   aopOp (right, ic, FALSE);
8446
8447   /* special case both in far space */
8448   if (AOP_TYPE (right) == AOP_DPTR &&
8449       IS_TRUE_SYMOP (result) &&
8450       isOperandInFarSpace (result))
8451     {
8452
8453       genFarFarAssign (result, right, ic);
8454       return;
8455     }
8456
8457   aopOp (result, ic, TRUE);
8458
8459   /* if they are the same registers */
8460   if (sameRegs (AOP (right), AOP (result)))
8461     goto release;
8462
8463   /* if the result is a bit */
8464   if (AOP_TYPE (result) == AOP_CRY)
8465     {
8466
8467       /* if the right size is a literal then
8468          we know what the value is */
8469       if (AOP_TYPE (right) == AOP_LIT)
8470         {
8471           if (((int) operandLitValue (right)))
8472             aopPut (AOP (result), one, 0);
8473           else
8474             aopPut (AOP (result), zero, 0);
8475           goto release;
8476         }
8477
8478       /* the right is also a bit variable */
8479       if (AOP_TYPE (right) == AOP_CRY)
8480         {
8481           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8482           aopPut (AOP (result), "c", 0);
8483           goto release;
8484         }
8485
8486       /* we need to or */
8487       toBoolean (right);
8488       aopPut (AOP (result), "a", 0);
8489       goto release;
8490     }
8491
8492   /* bit variables done */
8493   /* general case */
8494   size = AOP_SIZE (result);
8495   offset = 0;
8496   if (AOP_TYPE (right) == AOP_LIT)
8497     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8498   if ((size > 1) &&
8499       (AOP_TYPE (result) != AOP_REG) &&
8500       (AOP_TYPE (right) == AOP_LIT) &&
8501       !IS_FLOAT (operandType (right)) &&
8502       (lit < 256L))
8503     {
8504       emitcode ("clr", "a");
8505       while (size--)
8506         {
8507           if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8508             aopPut (AOP (result), "a", size);
8509           else
8510             aopPut (AOP (result),
8511                     aopGet (AOP (right), size, FALSE, FALSE),
8512                     size);
8513         }
8514     }
8515   else
8516     {
8517       while (size--)
8518         {
8519           aopPut (AOP (result),
8520                   aopGet (AOP (right), offset, FALSE, FALSE),
8521                   offset);
8522           offset++;
8523         }
8524     }
8525
8526 release:
8527   freeAsmop (right, NULL, ic, TRUE);
8528   freeAsmop (result, NULL, ic, TRUE);
8529 }
8530
8531 /*-----------------------------------------------------------------*/
8532 /* genJumpTab - genrates code for jump table                       */
8533 /*-----------------------------------------------------------------*/
8534 static void
8535 genJumpTab (iCode * ic)
8536 {
8537   symbol *jtab;
8538   char *l;
8539
8540   D(emitcode (";     genJumpTab",""));
8541
8542   aopOp (IC_JTCOND (ic), ic, FALSE);
8543   /* get the condition into accumulator */
8544   l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8545   MOVA (l);
8546   /* multiply by three */
8547   emitcode ("add", "a,acc");
8548   emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8549   freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8550
8551   jtab = newiTempLabel (NULL);
8552   emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8553   emitcode ("jmp", "@a+dptr");
8554   emitcode ("", "%05d$:", jtab->key + 100);
8555   /* now generate the jump labels */
8556   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8557        jtab = setNextItem (IC_JTLABELS (ic)))
8558     emitcode ("ljmp", "%05d$", jtab->key + 100);
8559
8560 }
8561
8562 /*-----------------------------------------------------------------*/
8563 /* genCast - gen code for casting                                  */
8564 /*-----------------------------------------------------------------*/
8565 static void
8566 genCast (iCode * ic)
8567 {
8568   operand *result = IC_RESULT (ic);
8569   sym_link *ctype = operandType (IC_LEFT (ic));
8570   sym_link *rtype = operandType (IC_RIGHT (ic));
8571   operand *right = IC_RIGHT (ic);
8572   int size, offset;
8573
8574   D(emitcode(";     genCast",""));
8575
8576   /* if they are equivalent then do nothing */
8577   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8578     return;
8579
8580   aopOp (right, ic, FALSE);
8581   aopOp (result, ic, FALSE);
8582
8583   /* if the result is a bit */
8584   if (IS_BITVAR(OP_SYMBOL(result)->type))
8585     {
8586       /* if the right size is a literal then
8587          we know what the value is */
8588       if (AOP_TYPE (right) == AOP_LIT)
8589         {
8590           if (((int) operandLitValue (right)))
8591             aopPut (AOP (result), one, 0);
8592           else
8593             aopPut (AOP (result), zero, 0);
8594
8595           goto release;
8596         }
8597
8598       /* the right is also a bit variable */
8599       if (AOP_TYPE (right) == AOP_CRY)
8600         {
8601           emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8602           aopPut (AOP (result), "c", 0);
8603           goto release;
8604         }
8605
8606       /* we need to or */
8607       toBoolean (right);
8608       aopPut (AOP (result), "a", 0);
8609       goto release;
8610     }
8611
8612   /* if they are the same size : or less */
8613   if (AOP_SIZE (result) <= AOP_SIZE (right))
8614     {
8615
8616       /* if they are in the same place */
8617       if (sameRegs (AOP (right), AOP (result)))
8618         goto release;
8619
8620       /* if they in different places then copy */
8621       size = AOP_SIZE (result);
8622       offset = 0;
8623       while (size--)
8624         {
8625           aopPut (AOP (result),
8626                   aopGet (AOP (right), offset, FALSE, FALSE),
8627                   offset);
8628           offset++;
8629         }
8630       goto release;
8631     }
8632
8633
8634   /* if the result is of type pointer */
8635   if (IS_PTR (ctype))
8636     {
8637
8638       int p_type;
8639       sym_link *type = operandType (right);
8640       sym_link *etype = getSpec (type);
8641
8642       /* pointer to generic pointer */
8643       if (IS_GENPTR (ctype))
8644         {
8645           if (IS_PTR (type))
8646             p_type = DCL_TYPE (type);
8647           else
8648             {
8649               if (SPEC_SCLS(etype)==S_REGISTER) {
8650                 // let's assume it is a generic pointer
8651                 p_type=GPOINTER;
8652               } else {
8653                 /* we have to go by the storage class */
8654                 p_type = PTR_TYPE (SPEC_OCLS (etype));
8655               }
8656             }
8657
8658           /* the first two bytes are known */
8659           size = GPTRSIZE - 1;
8660           offset = 0;
8661           while (size--)
8662             {
8663               aopPut (AOP (result),
8664                       aopGet (AOP (right), offset, FALSE, FALSE),
8665                       offset);
8666               offset++;
8667             }
8668           /* the last byte depending on type */
8669             {
8670                 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8671                 char gpValStr[10];
8672             
8673                 if (gpVal == -1)
8674                 {
8675                     // pointerTypeToGPByte will have bitched.
8676                     exit(1);
8677                 }
8678             
8679                 sprintf(gpValStr, "#0x%d", gpVal);
8680                 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8681             }       
8682           goto release;
8683         }
8684
8685       /* just copy the pointers */
8686       size = AOP_SIZE (result);
8687       offset = 0;
8688       while (size--)
8689         {
8690           aopPut (AOP (result),
8691                   aopGet (AOP (right), offset, FALSE, FALSE),
8692                   offset);
8693           offset++;
8694         }
8695       goto release;
8696     }
8697
8698   /* so we now know that the size of destination is greater
8699      than the size of the source */
8700   /* we move to result for the size of source */
8701   size = AOP_SIZE (right);
8702   offset = 0;
8703   while (size--)
8704     {
8705       aopPut (AOP (result),
8706               aopGet (AOP (right), offset, FALSE, FALSE),
8707               offset);
8708       offset++;
8709     }
8710
8711   /* now depending on the sign of the source && destination */
8712   size = AOP_SIZE (result) - AOP_SIZE (right);
8713   /* if unsigned or not an integral type */
8714   if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8715     {
8716       while (size--)
8717         aopPut (AOP (result), zero, offset++);
8718     }
8719   else
8720     {
8721       /* we need to extend the sign :{ */
8722       char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8723                         FALSE, FALSE);
8724       MOVA (l);
8725       emitcode ("rlc", "a");
8726       emitcode ("subb", "a,acc");
8727       while (size--)
8728         aopPut (AOP (result), "a", offset++);
8729     }
8730
8731   /* we are done hurray !!!! */
8732
8733 release:
8734   freeAsmop (right, NULL, ic, TRUE);
8735   freeAsmop (result, NULL, ic, TRUE);
8736
8737 }
8738
8739 /*-----------------------------------------------------------------*/
8740 /* genDjnz - generate decrement & jump if not zero instrucion      */
8741 /*-----------------------------------------------------------------*/
8742 static int
8743 genDjnz (iCode * ic, iCode * ifx)
8744 {
8745   symbol *lbl, *lbl1;
8746   if (!ifx)
8747     return 0;
8748
8749   D(emitcode (";     genDjnz",""));
8750
8751   /* if the if condition has a false label
8752      then we cannot save */
8753   if (IC_FALSE (ifx))
8754     return 0;
8755
8756   /* if the minus is not of the form
8757      a = a - 1 */
8758   if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8759       !IS_OP_LITERAL (IC_RIGHT (ic)))
8760     return 0;
8761
8762   if (operandLitValue (IC_RIGHT (ic)) != 1)
8763     return 0;
8764
8765   /* if the size of this greater than one then no
8766      saving */
8767   if (getSize (operandType (IC_RESULT (ic))) > 1)
8768     return 0;
8769
8770   /* otherwise we can save BIG */
8771   lbl = newiTempLabel (NULL);
8772   lbl1 = newiTempLabel (NULL);
8773
8774   aopOp (IC_RESULT (ic), ic, FALSE);
8775
8776   if (AOP_NEEDSACC(IC_RESULT(ic)))
8777   {
8778       /* If the result is accessed indirectly via
8779        * the accumulator, we must explicitly write
8780        * it back after the decrement.
8781        */
8782       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8783       
8784       if (strcmp(rByte, "a"))
8785       {
8786            /* Something is hopelessly wrong */
8787            fprintf(stderr, "*** warning: internal error at %s:%d\n",
8788                    __FILE__, __LINE__);
8789            /* We can just give up; the generated code will be inefficient,
8790             * but what the hey.
8791             */
8792            freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8793            return 0;
8794       }
8795       emitcode ("dec", "%s", rByte);
8796       aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8797       emitcode ("jnz", "%05d$", lbl->key + 100);
8798   }
8799   else if (IS_AOP_PREG (IC_RESULT (ic)))
8800     {
8801       emitcode ("dec", "%s",
8802                 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8803       emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8804       emitcode ("jnz", "%05d$", lbl->key + 100);
8805     }
8806   else
8807     {
8808       emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8809                 lbl->key + 100);
8810     }
8811   emitcode ("sjmp", "%05d$", lbl1->key + 100);
8812   emitcode ("", "%05d$:", lbl->key + 100);
8813   emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8814   emitcode ("", "%05d$:", lbl1->key + 100);
8815
8816   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8817   ifx->generated = 1;
8818   return 1;
8819 }
8820
8821 /*-----------------------------------------------------------------*/
8822 /* genReceive - generate code for a receive iCode                  */
8823 /*-----------------------------------------------------------------*/
8824 static void
8825 genReceive (iCode * ic)
8826 {
8827     int size = getSize (operandType (IC_RESULT (ic)));
8828     int offset = 0;
8829   D(emitcode (";     genReceive",""));
8830
8831   if (ic->argreg == 1) { /* first parameter */
8832       if (isOperandInFarSpace (IC_RESULT (ic)) &&
8833           (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8834            IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8835           
8836           offset = fReturnSizeMCS51 - size;
8837           while (size--) {
8838               emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8839                                        fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8840               offset++;
8841           }
8842           aopOp (IC_RESULT (ic), ic, FALSE);
8843           size = AOP_SIZE (IC_RESULT (ic));
8844           offset = 0;
8845           while (size--) {
8846               emitcode ("pop", "acc");
8847               aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8848           }
8849           
8850       } else {
8851           _G.accInUse++;
8852           aopOp (IC_RESULT (ic), ic, FALSE);
8853           _G.accInUse--;
8854           assignResultValue (IC_RESULT (ic));
8855       }
8856   } else { /* second receive onwards */
8857       int rb1off ;
8858       aopOp (IC_RESULT (ic), ic, FALSE);
8859       rb1off = ic->argreg;
8860       while (size--) {
8861           aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
8862       }
8863   }
8864   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8865 }
8866
8867 /*-----------------------------------------------------------------*/
8868 /* gen51Code - generate code for 8051 based controllers            */
8869 /*-----------------------------------------------------------------*/
8870 void
8871 gen51Code (iCode * lic)
8872 {
8873   iCode *ic;
8874   int cln = 0;
8875
8876   lineHead = lineCurr = NULL;
8877
8878   /* print the allocation information */
8879   if (allocInfo)
8880     printAllocInfo (currFunc, codeOutFile);
8881   /* if debug information required */
8882   if (options.debug && currFunc)
8883     {
8884       debugFile->writeFunction(currFunc);
8885       _G.debugLine = 1;
8886       if (IS_STATIC (currFunc->etype))
8887         emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8888       else
8889         emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8890       _G.debugLine = 0;
8891     }
8892   /* stack pointer name */
8893   if (options.useXstack)
8894     spname = "_spx";
8895   else
8896     spname = "sp";
8897
8898
8899   for (ic = lic; ic; ic = ic->next)
8900     {
8901
8902       if (ic->lineno && cln != ic->lineno)
8903         {
8904           if (options.debug)
8905             {
8906               _G.debugLine = 1;
8907               emitcode ("", "C$%s$%d$%d$%d ==.",
8908                         FileBaseName (ic->filename), ic->lineno,
8909                         ic->level, ic->block);
8910               _G.debugLine = 0;
8911             }
8912           if (!options.noCcodeInAsm) {
8913             emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno, 
8914                       printCLine(ic->filename, ic->lineno));
8915           }
8916           cln = ic->lineno;
8917         }
8918       if (options.iCodeInAsm) {
8919         emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
8920       }
8921       /* if the result is marked as
8922          spilt and rematerializable or code for
8923          this has already been generated then
8924          do nothing */
8925       if (resultRemat (ic) || ic->generated)
8926         continue;
8927
8928       /* depending on the operation */
8929       switch (ic->op)
8930         {
8931         case '!':
8932           genNot (ic);
8933           break;
8934
8935         case '~':
8936           genCpl (ic);
8937           break;
8938
8939         case UNARYMINUS:
8940           genUminus (ic);
8941           break;
8942
8943         case IPUSH:
8944           genIpush (ic);
8945           break;
8946
8947         case IPOP:
8948           /* IPOP happens only when trying to restore a
8949              spilt live range, if there is an ifx statement
8950              following this pop then the if statement might
8951              be using some of the registers being popped which
8952              would destory the contents of the register so
8953              we need to check for this condition and handle it */
8954           if (ic->next &&
8955               ic->next->op == IFX &&
8956               regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8957             genIfx (ic->next, ic);
8958           else
8959             genIpop (ic);
8960           break;
8961
8962         case CALL:
8963           genCall (ic);
8964           break;
8965
8966         case PCALL:
8967           genPcall (ic);
8968           break;
8969
8970         case FUNCTION:
8971           genFunction (ic);
8972           break;
8973
8974         case ENDFUNCTION:
8975           genEndFunction (ic);
8976           break;
8977
8978         case RETURN:
8979           genRet (ic);
8980           break;
8981
8982         case LABEL:
8983           genLabel (ic);
8984           break;
8985
8986         case GOTO:
8987           genGoto (ic);
8988           break;
8989
8990         case '+':
8991           genPlus (ic);
8992           break;
8993
8994         case '-':
8995           if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8996             genMinus (ic);
8997           break;
8998
8999         case '*':
9000           genMult (ic);
9001           break;
9002
9003         case '/':
9004           genDiv (ic);
9005           break;
9006
9007         case '%':
9008           genMod (ic);
9009           break;
9010
9011         case '>':
9012           genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9013           break;
9014
9015         case '<':
9016           genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9017           break;
9018
9019         case LE_OP:
9020         case GE_OP:
9021         case NE_OP:
9022
9023           /* note these two are xlated by algebraic equivalence
9024              during parsing SDCC.y */
9025           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9026                   "got '>=' or '<=' shouldn't have come here");
9027           break;
9028
9029         case EQ_OP:
9030           genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9031           break;
9032
9033         case AND_OP:
9034           genAndOp (ic);
9035           break;
9036
9037         case OR_OP:
9038           genOrOp (ic);
9039           break;
9040
9041         case '^':
9042           genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9043           break;
9044
9045         case '|':
9046           genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9047           break;
9048
9049         case BITWISEAND:
9050           genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9051           break;
9052
9053         case INLINEASM:
9054           genInline (ic);
9055           break;
9056
9057         case RRC:
9058           genRRC (ic);
9059           break;
9060
9061         case RLC:
9062           genRLC (ic);
9063           break;
9064
9065         case GETHBIT:
9066           genGetHbit (ic);
9067           break;
9068
9069         case LEFT_OP:
9070           genLeftShift (ic);
9071           break;
9072
9073         case RIGHT_OP:
9074           genRightShift (ic);
9075           break;
9076
9077         case GET_VALUE_AT_ADDRESS:
9078           genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9079           break;
9080
9081         case '=':
9082           if (POINTER_SET (ic))
9083             genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9084           else
9085             genAssign (ic);
9086           break;
9087
9088         case IFX:
9089           genIfx (ic, NULL);
9090           break;
9091
9092         case ADDRESS_OF:
9093           genAddrOf (ic);
9094           break;
9095
9096         case JUMPTABLE:
9097           genJumpTab (ic);
9098           break;
9099
9100         case CAST:
9101           genCast (ic);
9102           break;
9103
9104         case RECEIVE:
9105           genReceive (ic);
9106           break;
9107
9108         case SEND:
9109           addSet (&_G.sendSet, ic);
9110           break;
9111
9112         default:
9113           ic = ic;
9114         }
9115     }
9116
9117
9118   /* now we are ready to call the
9119      peep hole optimizer */
9120   if (!options.nopeep)
9121     peepHole (&lineHead);
9122
9123   /* now do the actual printing */
9124   printLine (lineHead, codeOutFile);
9125   return;
9126 }