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