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