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