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