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