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