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