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