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