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