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