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