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