Just to make sure I don't loose them again when syncing with cvs.
authorjohanknol <johanknol@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Thu, 17 Jan 2002 14:23:49 +0000 (14:23 +0000)
committerjohanknol <johanknol@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Thu, 17 Jan 2002 14:23:49 +0000 (14:23 +0000)
It is useless for now.

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@1809 4a8a32a2-be11-0410-ad9d-d568d2c75423

16 files changed:
configure
src/xa51/Makefile [new file with mode: 0644]
src/xa51/Makefile.bcc [new file with mode: 0644]
src/xa51/Makefile.dep [new file with mode: 0644]
src/xa51/gen.c [new file with mode: 0755]
src/xa51/gen.h [new file with mode: 0755]
src/xa51/gen.o [new file with mode: 0644]
src/xa51/main.c [new file with mode: 0755]
src/xa51/main.h [new file with mode: 0644]
src/xa51/main.o [new file with mode: 0644]
src/xa51/peeph.def [new file with mode: 0644]
src/xa51/peeph.rul [new file with mode: 0644]
src/xa51/port.a [new file with mode: 0644]
src/xa51/ralloc.c [new file with mode: 0755]
src/xa51/ralloc.h [new file with mode: 0755]
src/xa51/ralloc.o [new file with mode: 0644]

index 39e206cbadb96b2787ff94eb57c92f45f85feded..8939cada45d7d13d9a847ae3b4396155990572b9 100755 (executable)
--- a/configure
+++ b/configure
@@ -2801,9 +2801,9 @@ if test "$enable_xa51_port" = "no"; then
 EOF
 
 else
-    #echo xa51 >>ports.build // not yet
+    echo xa51 >>ports.build
     cat >> confdefs.h <<EOF
-#define OPT_DISABLE_XA51 1 // not yet
+#define OPT_DISABLE_XA51 0
 EOF
 
 fi
diff --git a/src/xa51/Makefile b/src/xa51/Makefile
new file mode 100644 (file)
index 0000000..3b85636
--- /dev/null
@@ -0,0 +1,2 @@
+# Make all in this directory
+include ../port.mk
diff --git a/src/xa51/Makefile.bcc b/src/xa51/Makefile.bcc
new file mode 100644 (file)
index 0000000..4b17a92
--- /dev/null
@@ -0,0 +1,22 @@
+PRJDIR = ../..
+
+# !include $(PRJDIR)/Makefile.common
+
+OBJ = gen.obj ralloc.obj main.obj
+LIB = port.lib
+
+!include ..\..\Bcc.inc
+CFLAGS  = -I.. -I. -I..\.. -I..\..\support
+
+all: $(LIB)
+
+main.obj: main.c peeph.rul
+
+$(LIB): peeph.rul $(OBJ)
+       del $(LIB)
+       tlib /a $(LIB) +gen.obj +ralloc.obj +main.obj
+       
+peeph.rul: peeph.def
+        gawk -f ../SDCCpeeph.awk peeph.def > peeph.rul
+
+# include clean.mk
diff --git a/src/xa51/Makefile.dep b/src/xa51/Makefile.dep
new file mode 100644 (file)
index 0000000..4635445
--- /dev/null
@@ -0,0 +1,23 @@
+gen.o: gen.c ../SDCCglobl.h ../../sdccconf.h \
+ ../../support/Util/SDCCerr.h ../../support/Util/newalloc.h \
+ ../common.h ../SDCCmem.h ../SDCCast.h ../SDCCsymt.h ../SDCChasht.h \
+ ../SDCCval.h ../SDCCset.h ../SDCCy.h ../SDCCbitv.h ../SDCCicode.h \
+ ../SDCClabel.h ../SDCCBBlock.h ../SDCCloop.h ../SDCCcse.h \
+ ../SDCCcflow.h ../SDCCdflow.h ../SDCClrange.h ../SDCCptropt.h \
+ ../SDCCopt.h ../SDCCglue.h ../SDCCpeeph.h ../asm.h ../port.h ralloc.h \
+ gen.h
+main.o: main.c ../common.h ../SDCCglobl.h ../../sdccconf.h \
+ ../../support/Util/SDCCerr.h ../SDCCmem.h ../SDCCast.h ../SDCCsymt.h \
+ ../SDCChasht.h ../SDCCval.h ../SDCCset.h ../SDCCy.h ../SDCCbitv.h \
+ ../SDCCicode.h ../SDCClabel.h ../SDCCBBlock.h ../SDCCloop.h \
+ ../SDCCcse.h ../SDCCcflow.h ../SDCCdflow.h ../SDCClrange.h \
+ ../SDCCptropt.h ../SDCCopt.h ../SDCCglue.h ../SDCCpeeph.h ../asm.h \
+ ../port.h ../../support/Util/newalloc.h main.h ralloc.h gen.h \
+ peeph.rul
+ralloc.o: ralloc.c ../common.h ../SDCCglobl.h ../../sdccconf.h \
+ ../../support/Util/SDCCerr.h ../SDCCmem.h ../SDCCast.h ../SDCCsymt.h \
+ ../SDCChasht.h ../SDCCval.h ../SDCCset.h ../SDCCy.h ../SDCCbitv.h \
+ ../SDCCicode.h ../SDCClabel.h ../SDCCBBlock.h ../SDCCloop.h \
+ ../SDCCcse.h ../SDCCcflow.h ../SDCCdflow.h ../SDCClrange.h \
+ ../SDCCptropt.h ../SDCCopt.h ../SDCCglue.h ../SDCCpeeph.h ../asm.h \
+ ../port.h ../../support/Util/newalloc.h ralloc.h gen.h
diff --git a/src/xa51/gen.c b/src/xa51/gen.c
new file mode 100755 (executable)
index 0000000..40427b9
--- /dev/null
@@ -0,0 +1,1213 @@
+/*-------------------------------------------------------------------------
+  SDCCgen51.c - source file for code generation for 8051
+
+  Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+         and -  Jean-Louis VERN.jlvern@writeme.com (1999)
+  Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+  In other words, you are welcome to use, share and improve this program.
+  You are forbidden to forbid anyone else to use, share and improve
+  what you give them.   Help stamp out software-hoarding!
+
+  Notes:
+  000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
+      Made everything static
+-------------------------------------------------------------------------*/
+
+//#define D(x)
+#define D(x) x
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "SDCCglobl.h"
+#include "newalloc.h"
+
+#ifdef HAVE_SYS_ISA_DEFS_H
+#include <sys/isa_defs.h>
+#else
+#ifdef HAVE_MACHINE_ENDIAN_H
+#include <machine/endian.h>
+#else
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#else
+#if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
+#warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
+#warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
+#endif
+#endif
+#endif
+#endif
+
+#include "common.h"
+#include "SDCCpeeph.h"
+#include "ralloc.h"
+#include "gen.h"
+
+#if defined(__BORLANDC__) || defined(_MSC_VER)
+#define STRCASECMP stricmp
+#else
+#define STRCASECMP strcasecmp
+#endif
+
+extern int allocInfo;
+
+/* this is the down and dirty file with all kinds of
+   kludgy & hacky stuff. This is what it is all about
+   CODE GENERATION for a specific MCU . some of the
+   routines may be reusable, will have to see */
+
+static struct
+  {
+    short inLine;
+    short debugLine;
+    short nRegsSaved;
+    set *sendSet;
+  }
+_G;
+
+extern int xa51_ptrRegReq;
+extern int xa51_nRegs;
+extern FILE *codeOutFile;
+
+static lineNode *lineHead = NULL;
+static lineNode *lineCurr = NULL;
+
+#define LSB     0
+#define MSB16   1
+#define MSB24   2
+#define MSB32   3
+
+/*-----------------------------------------------------------------*/
+/* emitcode - writes the code into a file : for now it is simple    */
+/*-----------------------------------------------------------------*/
+static void emitcode (char *inst, char *fmt,...) {
+  va_list ap;
+  char lb[INITIAL_INLINEASM];
+  char *lbp = lb;
+
+  va_start (ap, fmt);
+
+  if (inst && *inst)
+    {
+      if (fmt && *fmt)
+       sprintf (lb, "%s\t", inst);
+      else
+       sprintf (lb, "%s", inst);
+      vsprintf (lb + (strlen (lb)), fmt, ap);
+    }
+  else
+    vsprintf (lb, fmt, ap);
+
+  while (isspace ((int)*lbp))
+    lbp++;
+
+  if (lbp && *lbp)
+    lineCurr = (lineCurr ?
+               connectLine (lineCurr, newLineNode (lb)) :
+               (lineHead = newLineNode (lb)));
+  lineCurr->isInline = _G.inLine;
+  lineCurr->isDebug = _G.debugLine;
+  va_end (ap);
+}
+
+/*-----------------------------------------------------------------*/
+/* newAsmop - creates a new asmOp                                  */
+/*-----------------------------------------------------------------*/
+static asmop *
+newAsmop (short type)
+{
+  asmop *aop;
+
+  aop = Safe_calloc (1, sizeof (asmop));
+  aop->type = type;
+  return aop;
+}
+
+char *aopTypeName(asmop *aop) {
+  switch (aop->type)
+    {
+    case AOP_LIT: return "lit";
+    case AOP_REG: return "reg";
+    case AOP_DIR: return "dir";
+    case AOP_FAR: return "far";
+    case AOP_CODE: return "code";
+    case AOP_STK: return "stack";
+    case AOP_IMMD: return "imm";
+    case AOP_CRY: return "bit";
+    }
+  return "unknown";
+}
+
+/*-----------------------------------------------------------------*/
+/* aopForSym - for a true symbol                                   */
+/*-----------------------------------------------------------------*/
+static asmop *aopForSym(symbol *sym, bool result) {
+  asmop *aop;
+
+  sym->aop = aop = newAsmop(0);
+  aop->size=getSize(sym->type);
+
+  // if it is in registers
+  if (sym->nRegs && sym->regs[0]) {
+    aop->type=AOP_REG;
+    if (sym->regs[1]) {
+      sprintf (aop->name[1], sym->regs[1]->name);
+    }
+    sprintf (aop->name[0], sym->regs[0]->name);
+    return aop;
+  }
+
+  // if it is on stack
+  if (sym->onStack) {
+    aop->type=AOP_STK;
+    sprintf (aop->name[0], "[r7+%d+0+%d+%d]", sym->stack, 
+            FUNC_ISISR(currFunc->type) ? 6 : 4, _G.nRegsSaved);
+    sprintf (aop->name[1], "[r7+%d+2+%d+%d]", sym->stack,
+            FUNC_ISISR(currFunc->type) ? 6 : 4, _G.nRegsSaved);
+    return aop;
+  }
+
+  // if it has a spillLoc
+  if (sym->usl.spillLoc) {
+    return aopForSym (sym->usl.spillLoc, result);
+  }
+
+  // if in bit space
+  if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
+    aop->type=AOP_CRY;
+    sprintf (aop->name[0], sym->rname);
+    return aop;
+  }
+
+  // if in direct space
+  if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
+    aop->type=AOP_DIR;
+    sprintf (aop->name[0], sym->rname);
+    sprintf (aop->name[1], "#0x%02x", POINTER);
+    return aop;
+  }
+
+  // if in code space
+  if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
+    if (result) {
+      fprintf (stderr, "aopForSym: result can not be in code space\n");
+      exit (1);
+    }
+    aop->type=AOP_CODE;
+    emitcode ("mov", "r0,#%s", sym->rname);
+    sprintf (aop->name[0], "r0");
+    sprintf (aop->name[1], "#0x%02x", CPOINTER);
+    return aop;
+  }
+
+  // if in far space
+  if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
+    aop->type=AOP_FAR;
+    emitcode ("mov", "r0,#%s", sym->rname);
+    sprintf (aop->name[0], "[r0]");
+    if (result) {
+      sprintf (aop->name[1], "[r0+2]");
+    } else {
+      sprintf (aop->name[1], "#0x%02x", FPOINTER);
+    }
+    return aop;
+  }
+
+  // special case for a function
+  if (IS_FUNC (sym->type)) {
+    aop->type=AOP_IMMD;
+    sprintf (aop->name[0], sym->rname);
+    return aop;
+  }
+
+  fprintf (stderr, "aopForSym (%s): What's up?\n", sym->name);
+  exit (1);
+}
+
+/*-----------------------------------------------------------------*/
+/* aopForVal - for a value                                         */
+/*-----------------------------------------------------------------*/
+static asmop *aopForVal(operand *op) {
+  asmop *aop;
+  long v=floatFromVal(OP_VALUE(op));
+
+  if (IS_OP_LITERAL(op)) {
+    op->aop = aop = newAsmop (AOP_LIT);
+    switch ((aop->size=getSize(operandType(op))))
+      {
+      case 1:
+       sprintf (aop->name[0], "#0x%02lx", v);
+       break;
+      case 2:
+       sprintf (aop->name[0], "#0x%04lx", v);
+       break;
+      case 4:
+       sprintf (aop->name[0], "#(0x%08lx >> 16)", v);
+       sprintf (aop->name[1], "#(0x%08lx & 0xffff)", v);
+       break;
+      default:
+       fprintf (stderr, "aopForVal (lit): unknown size\n");
+       exit (1);
+      }
+    return aop;
+  }
+
+  // must be immediate
+  if (IS_SYMOP(op)) {
+    op->aop = aop = newAsmop (AOP_IMMD);
+    switch ((aop->size=getSize(OP_SYMBOL(op)->type))) 
+      {
+      case 1:
+      case 2:
+       sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
+       return aop;
+      case 3: // generic pointer
+       sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
+       sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
+       return aop;
+      }
+  }
+  fprintf (stderr, "aopForVal: unknown type\n");
+  exit (1);
+  return NULL;
+}
+
+static void aopOp(operand *op, bool result) {
+
+  if (IS_SYMOP(op)) {
+    op->aop=aopForSym (OP_SYMBOL(op), result);
+    return;
+  }
+  if (IS_VALOP(op)) {
+    if (result) {
+      fprintf (stderr, "aopOp: result can not be a value\n");
+      exit (1);
+    }
+    aopForVal (op);
+    return;
+  }
+
+  fprintf (stderr, "aopOp: unexpected operand\n");
+  exit (1);
+}
+
+char *opRegName(operand *op, int offset, char *opName) {
+
+  if (IS_SYMOP(op)) {
+    if (OP_SYMBOL(op)->onStack) {
+      sprintf (aop->name[0], "[r7+%d+0+%d+%d]", sym->stack, 
+              FUNC_ISISR(currFunc->type) ? 6 : 4, _G.nRegsSaved);
+      return opName;
+    }
+    if (IS_TRUE_SYMOP(op))
+      return OP_SYMBOL(op)->rname;
+    else if (OP_SYMBOL(op)->regs[offset])
+      return OP_SYMBOL(op)->regs[offset]->name;
+    else
+      return "NULL";
+  }
+
+  if (IS_VALOP(op)) {
+    switch (SPEC_NOUN(OP_VALUE(op)->type)) {
+    case V_BIT:
+      if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
+         SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
+       fprintf (stderr, "opRegName: invalid bit value (%d)\n",
+                SPEC_CVAL(OP_VALUE(op)->type).v_int);
+       exit (1);
+      }
+      // fall through
+    case V_CHAR:
+      sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
+      break;
+    case V_INT:
+      if (SPEC_LONG(OP_VALUE(op)->type)) {
+       sprintf (opName, "#0x%02lx", SPEC_CVAL(OP_VALUE(op)->type).v_long);
+      } else {
+       sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
+      }
+      break;
+    case V_FLOAT:
+      sprintf (opName, "#0x%02lx", SPEC_CVAL(OP_VALUE(op)->type).v_long);
+      break;
+    default: 
+      fprintf (stderr, "opRegName: unexpected noun\n");
+      exit (1);
+    }
+    return opName;
+  }
+  fprintf (stderr, "opRegName: unexpected operand type\n");
+  exit (1);
+  return NULL; // to keep the compiler happy
+}
+
+char * printOp (operand *op) {
+  static char line[132];
+  bool isPtr = op->isPtr | op->isGptr;
+
+  if (IS_SYMOP(op)) {
+    symbol *sym=OP_SYMBOL(op);
+    if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
+      sym=SYM_SPIL_LOC(sym);
+    }
+    if (isPtr) {
+      sprintf (line, "[%s]:", sym->name);
+    } else {
+      sprintf (line, "%s:", sym->name);
+    }
+    if (sym->regs[0]) {
+      strcat (line, sym->regs[0]->name);
+      if (sym->regs[1]) {
+       strcat (line, ",");
+       strcat (line, sym->regs[1]->name);
+      }
+      return line;
+    }
+    if (sym->onStack) {
+      sprintf (line+strlen(line), "stack+%d", sym->stack);
+      return line;
+    }
+    if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
+      strcat (line, "far");
+      return line;
+    }
+    if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
+      strcat (line, "bit");
+      return line;
+    }
+    if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
+      strcat (line, "dir");
+      return line;
+    }
+    strcat (line, "unknown");
+    return line;
+  } else if (IS_VALOP(op)) {
+    opRegName(op, 0, line);
+  } else if (IS_TYPOP(op)) {
+    sprintf (line, "(");
+    // forget about static, volatile, ... for now
+    if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
+    if (SPEC_LONG(operandType(op))) strcat (line, "long ");
+    strcat (line, nounName(operandType(op)));
+    strcat (line, ")");
+  } else {
+    fprintf (stderr, "printOp: unexpected operand type\n");
+    exit (1);
+  }
+  return line;
+}
+
+void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
+  char line[132];
+
+  sprintf (line, "%s", op);
+  if (result) {
+    strcat (line, " result=");
+    strcat (line, printOp (IC_RESULT(ic)));
+  }
+  if (left) {
+    strcat (line, " left=");
+    strcat (line, printOp (IC_LEFT(ic)));
+  }
+  if (right) {
+    strcat (line, " right=");
+    strcat (line, printOp (IC_RIGHT(ic)));
+  }
+  emitcode (";", line);
+}
+
+/*-----------------------------------------------------------------*/
+/* toBoolean - return bit for operand!=0                           */
+/*-----------------------------------------------------------------*/
+static char *toBoolean (operand * op) {
+  switch (AOP_SIZE(op)) 
+    {
+    case 1:
+    case 2:
+      emitcode ("cmp", "%s,#0", AOP_NAME(op));
+      return "z";
+    }
+
+  fprintf (stderr, "toBoolean: unknown size %d\n", AOP_SIZE(op));
+  exit (1);
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* regsInCommon - two operands have some registers in common       */
+/*-----------------------------------------------------------------*/
+static bool regsInCommon (operand * op1, operand * op2) {
+  symbol *sym1, *sym2;
+  int i;
+
+  /* if they have registers in common */
+  if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
+    return FALSE;
+
+  sym1 = OP_SYMBOL (op1);
+  sym2 = OP_SYMBOL (op2);
+
+  if (sym1->nRegs == 0 || sym2->nRegs == 0)
+    return FALSE;
+
+  for (i = 0; i < sym1->nRegs; i++)
+    {
+      int j;
+      if (!sym1->regs[i])
+       continue;
+
+      for (j = 0; j < sym2->nRegs; j++)
+       {
+         if (!sym2->regs[j])
+           continue;
+
+         if (sym2->regs[j] == sym1->regs[i])
+           return TRUE;
+       }
+    }
+
+  return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* resultRemat - result  is rematerializable                       */
+/*-----------------------------------------------------------------*/
+static int resultRemat (iCode * ic) {
+  if (SKIP_IC (ic) || ic->op == IFX)
+    return 0;
+  
+  if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
+    {
+      symbol *sym = OP_SYMBOL (IC_RESULT (ic));
+      if (sym->remat && !POINTER_SET (ic))
+       return 1;
+    }
+  
+  return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* genNot - generate code for ! operation                          */
+/*-----------------------------------------------------------------*/
+static void genNot (iCode * ic) {
+  printIc("genNot:", ic, 1,1,0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genCpl - generate code for complement                           */
+/*-----------------------------------------------------------------*/
+static void genCpl (iCode * ic) {
+  printIc("genCpl", ic, 1,1,0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genUminus - unary minus code generation                         */
+/*-----------------------------------------------------------------*/
+static void genUminus (iCode * ic) {
+  printIc("genUminus", ic, 1,1,0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genIpush - genrate code for pushing this gets a little complex  */
+/*-----------------------------------------------------------------*/
+static void genIpush (iCode * ic) {
+  printIc ("genIpush", ic, 0,1,0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genIpop - recover the registers: can happen only for spilling   */
+/*-----------------------------------------------------------------*/
+static void genIpop (iCode * ic) {
+  printIc ("genIpop", ic, 0,1,0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genCall - generates a call statement                            */
+/*-----------------------------------------------------------------*/
+static void genCall (iCode * ic) {
+  emitcode (";", "genCall %s", OP_SYMBOL(IC_LEFT(ic))->name);
+}
+
+/*-----------------------------------------------------------------*/
+/* genPcall - generates a call by pointer statement                */
+/*-----------------------------------------------------------------*/
+static void
+genPcall (iCode * ic)
+{
+  emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
+}
+
+/*-----------------------------------------------------------------*/
+/* genFunction - generated code for function entry                 */
+/*-----------------------------------------------------------------*/
+static void genFunction (iCode * ic) {
+  symbol *sym=OP_SYMBOL(IC_LEFT(ic));
+  sym_link *type=sym->type;
+
+  emitcode (";", "-----------------------------------------");
+  emitcode (";", " function %s", sym->name);
+  emitcode (";", "-----------------------------------------");
+  
+  emitcode ("", "%s:", sym->rname);
+
+  if (IFFUNC_ISNAKED(type))
+  {
+      emitcode(";", "naked function: no prologue.");
+      return;
+  }
+
+  /* if critical function then turn interrupts off */
+  if (IFFUNC_ISCRITICAL (type))
+    emitcode ("clr", "ea");
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genEndFunction - generates epilogue for functions               */
+/*-----------------------------------------------------------------*/
+static void
+genEndFunction (iCode * ic)
+{
+  symbol *sym = OP_SYMBOL (IC_LEFT (ic));
+
+  if (IFFUNC_ISNAKED(sym->type))
+  {
+      emitcode(";", "naked function: no epilogue.");
+      return;
+  }
+
+  printIc ("genEndFunction", ic, 0,0,0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRet - generate code for return statement                     */
+/*-----------------------------------------------------------------*/
+static void genRet (iCode * ic) {
+  emitcode (";", "genRet");
+}
+
+/*-----------------------------------------------------------------*/
+/* genLabel - generates a label                                    */
+/*-----------------------------------------------------------------*/
+static void genLabel (iCode * ic) {
+  /* special case never generate */
+  if (IC_LABEL (ic) == entryLabel)
+    return;
+
+  emitcode (";", "genLabel %s", IC_LABEL(ic)->name);
+  emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
+}
+
+/*-----------------------------------------------------------------*/
+/* genGoto - generates a ljmp                                      */
+/*-----------------------------------------------------------------*/
+static void genGoto (iCode * ic) {
+  emitcode (";", "genGoto %s", IC_LABEL(ic)->name);
+  emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
+}
+
+/*-----------------------------------------------------------------*/
+/* genPlus - generates code for addition                           */
+/*-----------------------------------------------------------------*/
+static void genPlus (iCode * ic) {
+  printIc ("genPlus", ic, 1,1,1);
+}
+
+/*-----------------------------------------------------------------*/
+/* genMinus - generates code for subtraction                       */
+/*-----------------------------------------------------------------*/
+static void genMinus (iCode * ic) {
+  printIc ("genMinus", ic, 1,1,1);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genMult - generates code for multiplication                     */
+/*-----------------------------------------------------------------*/
+static void genMult (iCode * ic) {
+  printIc ("genMult", ic, 1,1,1);
+}
+
+/*-----------------------------------------------------------------*/
+/* genDiv - generates code for division                            */
+/*-----------------------------------------------------------------*/
+static void genDiv (iCode * ic) {
+  printIc ("genDiv", ic, 1,1,1);
+}
+
+/*-----------------------------------------------------------------*/
+/* genMod - generates code for division                            */
+/*-----------------------------------------------------------------*/
+static void genMod (iCode * ic) {
+  printIc ("genMod", ic, 1,1,1);
+}
+
+/*-----------------------------------------------------------------*/
+/* genCmpGt :- greater than comparison                             */
+/*-----------------------------------------------------------------*/
+static void genCmpGt (iCode * ic, iCode * ifx) {
+  printIc ("genCmpGt", ic, 1,1,1);
+}
+/*-----------------------------------------------------------------*/
+/* genCmpLt - less than comparisons                                */
+/*-----------------------------------------------------------------*/
+static void genCmpLt (iCode * ic, iCode * ifx) {
+  printIc ("genCmpLt", ic, 1,1,1);
+}
+/*-----------------------------------------------------------------*/
+/* genCmpEq - generates code for equal to                          */
+/*-----------------------------------------------------------------*/
+static void genCmpEq (iCode * ic, iCode * ifx) {
+  printIc ("genCmpEq", ic, 1,1,1);
+}
+
+/*-----------------------------------------------------------------*/
+/* ifxForOp - returns the icode containing the ifx for operand     */
+/*-----------------------------------------------------------------*/
+static iCode *ifxForOp (operand * op, iCode * ic) {
+  /* if true symbol then needs to be assigned */
+  if (IS_TRUE_SYMOP (op))
+    return NULL;
+  
+  /* if this has register type condition and
+     the next instruction is ifx with the same operand
+     and live to of the operand is upto the ifx only then */
+  if (ic->next &&
+      ic->next->op == IFX &&
+      IC_COND (ic->next)->key == op->key &&
+      OP_SYMBOL (op)->liveTo <= ic->next->seq)
+    return ic->next;
+  
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* hasInc - operand is incremented before any other use            */
+/*-----------------------------------------------------------------*/
+static iCode *hasInc (operand *op, iCode *ic, int osize) {
+  sym_link *type = operandType(op);
+  sym_link *retype = getSpec (type);
+  iCode *lic = ic->next;
+  int isize ;
+  
+  /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
+  if (!IS_SYMOP(op)) return NULL;
+
+  if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
+  if (IS_AGGREGATE(type->next)) return NULL;
+  if (osize != (isize = getSize(type->next))) return NULL;
+
+  while (lic) {
+    /* if operand of the form op = op + <sizeof *op> */
+    if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
+       isOperandEqual(IC_RESULT(lic),op) && 
+       isOperandLiteral(IC_RIGHT(lic)) &&
+       operandLitValue(IC_RIGHT(lic)) == isize) {
+      return lic;
+    }
+    /* if the operand used or deffed */
+    if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
+      return NULL;
+    }
+    /* if GOTO or IFX */
+    if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
+    lic = lic->next;
+  }
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* genAndOp - for && operation                                     */
+/*-----------------------------------------------------------------*/
+static void genAndOp (iCode * ic) {
+  printIc ("genAndOp(&&)", ic, 1,1,1);
+}
+
+/*-----------------------------------------------------------------*/
+/* genOrOp - for || operation                                      */
+/*-----------------------------------------------------------------*/
+static void genOrOp (iCode * ic) {
+  printIc ("genOrOp(||)", ic, 1,1,1);
+}
+
+/*-----------------------------------------------------------------*/
+/* genAnd  - code for and                                            */
+/*-----------------------------------------------------------------*/
+static void genAnd (iCode * ic, iCode * ifx) {
+  printIc ("genAnd", ic, 1,1,1);
+}
+
+/*-----------------------------------------------------------------*/
+/* genOr  - code for or                                            */
+/*-----------------------------------------------------------------*/
+static void genOr (iCode * ic, iCode * ifx) {
+  printIc ("genOr", ic, 1,1,1);
+}
+
+/*-----------------------------------------------------------------*/
+/* genXor - code for xclusive or                                   */
+/*-----------------------------------------------------------------*/
+static void genXor (iCode * ic, iCode * ifx) {
+  printIc ("genXor", ic, 1,1,1);
+}
+
+/*-----------------------------------------------------------------*/
+/* genInline - write the inline code out                           */
+/*-----------------------------------------------------------------*/
+static void genInline (iCode * ic) {
+  printIc ("genInline", ic, 0,0,0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRRC - rotate right with carry                                */
+/*-----------------------------------------------------------------*/
+static void genRRC (iCode * ic) {
+  printIc ("genRRC", ic, 1,1,0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRLC - generate code for rotate left with carry               */
+/*-----------------------------------------------------------------*/
+static void genRLC (iCode * ic) {
+  printIc ("genRLC", ic, 1,1,0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genGetHbit - generates code get highest order bit               */
+/*-----------------------------------------------------------------*/
+static void genGetHbit (iCode * ic) {
+  printIc ("genGetHbit", ic, 1,1,0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genLeftShift - generates code for left shifting                 */
+/*-----------------------------------------------------------------*/
+static void genLeftShift (iCode * ic) {
+  printIc ("genLeftShift", ic, 1,1,1);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRightShift - generate code for right shifting                */
+/*-----------------------------------------------------------------*/
+static void genRightShift (iCode * ic) {
+  printIc ("genRightShift", ic, 1,1,1);
+}
+
+/*-----------------------------------------------------------------*/
+/* genPointerGet - generate code for pointer get                   */
+/*-----------------------------------------------------------------*/
+static void genPointerGet (iCode * ic, iCode *pi) {
+  printIc ("genPointerGet", ic, 1,1,0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genPointerSet - stores the value into a pointer location        */
+/*-----------------------------------------------------------------*/
+static void genPointerSet (iCode * ic, iCode *pi) {
+  printIc ("genPointerSet", ic, 1,0,1);
+}
+
+/*-----------------------------------------------------------------*/
+/* genIfx - generate code for Ifx statement                        */
+/*-----------------------------------------------------------------*/
+static void genIfx (iCode * ic, iCode * popIc) {
+  bool trueOrFalse;
+  symbol *jlbl, *tlbl;
+  operand *cond=IC_COND(ic);
+
+  emitcode (";", "genIfx cond=%s trueLabel:%s falseLabel:%s", 
+           printOp(cond),
+           IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
+           IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
+
+  aopOp(cond,FALSE);
+
+  if (IC_TRUE(ic)) {
+    trueOrFalse=TRUE;
+    jlbl=IC_TRUE(ic);
+  } else {
+    trueOrFalse=FALSE;
+    jlbl=IC_FALSE(ic);
+  }
+
+  switch (AOP_TYPE(cond) )
+    {
+    case AOP_CRY:
+      emitcode (trueOrFalse ? "jb" : "jbc", "%s,%05d$", 
+               AOP_NAME(cond)[0], jlbl->key+100);
+      return;
+    case AOP_REG:
+    case AOP_DIR:
+    case AOP_FAR:
+      tlbl=newiTempLabel(NULL);
+      emitcode ("cmp", "%s,#0", AOP_NAME(cond)[0]);
+      emitcode (trueOrFalse ? "bne" : "beq", "%05d$", tlbl->key+100);
+      if (*AOP_NAME(cond)[1]) {
+       emitcode ("cmp", "%s,#0", AOP_NAME(cond)[1]);
+       emitcode (trueOrFalse ? "bne" : "beq", "%05d$", tlbl->key+100);
+      }
+      emitcode ("jmp", "%05d$", jlbl->key+100);
+      emitcode ("", "%05d$:", tlbl->key+100);
+      return;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genAddrOf - generates code for address of                       */
+/*-----------------------------------------------------------------*/
+static void genAddrOf (iCode * ic) {
+  printIc ("genAddrOf", ic, 1,1,0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genAssign - generate code for assignment                        */
+/*-----------------------------------------------------------------*/
+static void genAssign (iCode * ic) {
+  operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
+
+  printIc ("genAssign", ic, 1,0,1);
+  
+  if (!IS_SYMOP(result)) {
+    fprintf (stderr, "genAssign: result is not a symbol\n");
+    exit (1);
+  }
+  
+  aopOp(right, FALSE);
+  aopOp(result, TRUE);
+
+  if (result->aop->type==AOP_REG || 
+      right->aop->type==AOP_REG ||
+      right->aop->type==AOP_LIT ||
+      right->aop->type==AOP_IMMD) {
+    // everything will do
+  } else {
+    // they have to match
+    if (result->aop->type != right->aop->type) {
+      fprintf (stderr, "genAssign: types don't match (%s!=%s)\n",
+              aopTypeName(result->aop), aopTypeName(right->aop));
+      exit (1);
+    }
+  }
+
+  /* if result is a bit */
+  if (AOP_TYPE(result) == AOP_CRY) {
+    /* if right is literal, we know what the value is */
+    if (AOP_TYPE(right) == AOP_LIT) {
+      if (operandLitValue(right)) {
+       emitcode ("setb", AOP_NAME(result)[0]);
+      } else {
+       emitcode ("clr", AOP_NAME(result)[0]);
+      }
+      return;
+    }
+    /* if right is also a bit */
+    if (AOP_TYPE(right) == AOP_CRY) {
+      emitcode ("mov", "c,%s", AOP_NAME(right));
+      emitcode ("mov", "%s,c", AOP_NAME(result));
+      return;
+    }
+    /* we need to or */
+    emitcode ("mov", "%s,%s", AOP_NAME(result), toBoolean(right));
+    return;
+  }
+
+  /* general case */
+  emitcode ("mov", "%s,%s", 
+           result->aop->name[0], right->aop->name[0]);
+  if (IS_GENPTR(operandType(result))) {
+    emitcode ("mov", "%s,%s",
+             result->aop->name[1], right->aop->name[1]);
+  }
+  
+}
+
+/*-----------------------------------------------------------------*/
+/* genJumpTab - genrates code for jump table                       */
+/*-----------------------------------------------------------------*/
+static void genJumpTab (iCode * ic) {
+  printIc ("genJumpTab", ic, 0,0,0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genCast - gen code for casting                                  */
+/*-----------------------------------------------------------------*/
+static void genCast (iCode * ic) {
+  printIc ("genCast", ic, 1,1,1);
+}
+
+/*-----------------------------------------------------------------*/
+/* genDjnz - generate decrement & jump if not zero instrucion      */
+/*-----------------------------------------------------------------*/
+static bool genDjnz (iCode * ic, iCode * ifx) {
+  printIc ("genDjnz", ic, 0,0,0);
+  return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* genReceive - generate code for a receive iCode                  */
+/*-----------------------------------------------------------------*/
+static void genReceive (iCode * ic) {
+  printIc ("genReceive", ic, 1,0,0);
+}
+
+/*-----------------------------------------------------------------*/
+/* gen51Code - generate code for 8051 based controllers            */
+/*-----------------------------------------------------------------*/
+void genXA51Code (iCode * lic) {
+  iCode *ic;
+  int cln = 0;
+  
+  fprintf (stderr, "genXA51Code\n");
+  lineHead = lineCurr = NULL;
+  
+  /* print the allocation information */
+  if (allocInfo)
+    printAllocInfo (currFunc, codeOutFile);
+
+  /* if debug information required */
+  if (options.debug && currFunc)
+    {
+      cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
+      _G.debugLine = 1;
+      if (IS_STATIC (currFunc->etype))
+       emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
+      else
+       emitcode ("", "G$%s$0$0 ==.", currFunc->name);
+      _G.debugLine = 0;
+    }
+  
+  for (ic = lic; ic; ic = ic->next) {
+    if (cln != ic->lineno) {
+      if (options.debug) {
+       _G.debugLine = 1;
+       emitcode ("", "C$%s$%d$%d$%d ==.",
+                 FileBaseName (ic->filename), ic->lineno,
+                 ic->level, ic->block);
+       _G.debugLine = 0;
+      }
+      emitcode (";", "%s %d", ic->filename, ic->lineno);
+      cln = ic->lineno;
+    }
+    /* if the result is marked as
+       spilt and rematerializable or code for
+       this has already been generated then
+       do nothing */
+    if (resultRemat (ic) || ic->generated)
+      continue;
+    
+    /* depending on the operation */
+    switch (ic->op)
+      {
+      case '!':
+       genNot (ic);
+       break;
+       
+      case '~':
+       genCpl (ic);
+       break;
+       
+      case UNARYMINUS:
+       genUminus (ic);
+       break;
+       
+      case IPUSH:
+       genIpush (ic);
+       break;
+       
+      case IPOP:
+       /* IPOP happens only when trying to restore a
+          spilt live range, if there is an ifx statement
+          following this pop then the if statement might
+          be using some of the registers being popped which
+          would destory the contents of the register so
+          we need to check for this condition and handle it */
+       if (ic->next &&
+           ic->next->op == IFX &&
+           regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
+         genIfx (ic->next, ic);
+       else
+         genIpop (ic);
+       break;
+       
+      case CALL:
+       genCall (ic);
+       break;
+       
+      case PCALL:
+       genPcall (ic);
+       break;
+       
+      case FUNCTION:
+       genFunction (ic);
+       break;
+       
+      case ENDFUNCTION:
+       genEndFunction (ic);
+       break;
+       
+      case RETURN:
+       genRet (ic);
+       break;
+       
+      case LABEL:
+       genLabel (ic);
+       break;
+       
+      case GOTO:
+       genGoto (ic);
+       break;
+       
+      case '+':
+       genPlus (ic);
+       break;
+       
+      case '-':
+       if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
+         genMinus (ic);
+       break;
+       
+      case '*':
+       genMult (ic);
+       break;
+       
+      case '/':
+       genDiv (ic);
+       break;
+       
+      case '%':
+       genMod (ic);
+       break;
+       
+      case '>':
+       genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
+       break;
+       
+      case '<':
+       genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
+       break;
+       
+      case LE_OP:
+      case GE_OP:
+      case NE_OP:
+       
+       /* note these two are xlated by algebraic equivalence
+          during parsing SDCC.y */
+       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+               "got '>=' or '<=' shouldn't have come here");
+       break;
+       
+      case EQ_OP:
+       genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
+       break;
+       
+      case AND_OP:
+       genAndOp (ic);
+       break;
+       
+      case OR_OP:
+       genOrOp (ic);
+       break;
+       
+      case '^':
+       genXor (ic, ifxForOp (IC_RESULT (ic), ic));
+       break;
+       
+      case '|':
+       genOr (ic, ifxForOp (IC_RESULT (ic), ic));
+       break;
+       
+      case BITWISEAND:
+       genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
+       break;
+       
+      case INLINEASM:
+       genInline (ic);
+       break;
+       
+      case RRC:
+       genRRC (ic);
+       break;
+       
+      case RLC:
+       genRLC (ic);
+       break;
+       
+      case GETHBIT:
+       genGetHbit (ic);
+       break;
+       
+      case LEFT_OP:
+       genLeftShift (ic);
+       break;
+       
+      case RIGHT_OP:
+       genRightShift (ic);
+       break;
+       
+      case GET_VALUE_AT_ADDRESS:
+       genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_LEFT(ic)))));
+       break;
+       
+      case '=':
+       if (POINTER_SET (ic))
+         genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
+       else
+         genAssign (ic);
+       break;
+       
+      case IFX:
+       genIfx (ic, NULL);
+       break;
+       
+      case ADDRESS_OF:
+       genAddrOf (ic);
+       break;
+       
+      case JUMPTABLE:
+       genJumpTab (ic);
+       break;
+       
+      case CAST:
+       genCast (ic);
+       break;
+       
+      case RECEIVE:
+       genReceive (ic);
+       break;
+       
+      case SEND:
+       addSet (&_G.sendSet, ic);
+       break;
+       
+      default:
+       ic = ic;
+      }
+  }
+  
+  
+  /* now we are ready to call the
+     peep hole optimizer */
+  if (!options.nopeep)
+    peepHole (&lineHead);
+  
+  /* now do the actual printing */
+  printLine (lineHead, codeOutFile);
+  return;
+}
diff --git a/src/xa51/gen.h b/src/xa51/gen.h
new file mode 100755 (executable)
index 0000000..bd45124
--- /dev/null
@@ -0,0 +1,65 @@
+/*-------------------------------------------------------------------------
+  SDCCgen51.h - header file for code generation for 8051
+
+             Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!  
+-------------------------------------------------------------------------*/
+
+#ifndef SDCCGEN51_H
+#define SDCCGEN51_H
+
+enum
+  {
+    AOP_LIT = 1,
+    AOP_REG, 
+    AOP_DIR, 
+    AOP_FAR,
+    AOP_CODE,
+    AOP_STK, 
+    AOP_IMMD, 
+    AOP_CRY
+  };
+
+/* type asmop : a homogenised type for 
+   all the different spaces an operand can be
+   in */
+typedef struct asmop {
+  
+  short type;                  
+  /* can have values
+     AOP_LIT    -  operand is a literal value
+     AOP_REG    -  is in registers
+     AOP_DIR    -  direct, just a name
+     AOP_FAR    -  
+     AOP_CODE   - 
+     AOP_STK    -  on stack (with offset)
+     AOP_IMMD   -  immediate value for eg. remateriazable 
+     AOP_CRY    -  carry contains the value of this
+  */
+  short size; /* size of this aop */
+  char name[2][64]; /* can be "r0" "r6h" [rxbw+y] "#..." */
+} asmop;
+
+#define AOP(x) x->aop
+#define AOP_TYPE(x) x->aop->type
+#define AOP_SIZE(x) x->aop->size
+#define AOP_NAME(x) x->aop->name
+
+#endif
diff --git a/src/xa51/gen.o b/src/xa51/gen.o
new file mode 100644 (file)
index 0000000..2105af6
Binary files /dev/null and b/src/xa51/gen.o differ
diff --git a/src/xa51/main.c b/src/xa51/main.c
new file mode 100755 (executable)
index 0000000..9021f59
--- /dev/null
@@ -0,0 +1,285 @@
+/** @file main.c
+    xa51 specific general functions.
+
+    Note that mlh prepended _xa51_ on the static functions.  Makes
+    it easier to set a breakpoint using the debugger.
+*/
+#include "common.h"
+#include "main.h"
+#include "ralloc.h"
+#include "gen.h"
+
+static char _defaultRules[] =
+{
+#include "peeph.rul"
+};
+
+/* list of key words used by xa51 */
+static char *_xa51_keywords[] =
+{
+  "at",
+  "bit",
+  "code",
+  "critical",
+  "data",
+  "far",
+  //"idata",
+  "interrupt",
+  "near",
+  //"pdata",
+  "reentrant",
+  "sfr",
+  "sbit",
+  "using",
+  //"xdata",
+  //"_data",
+  //"_code",
+  //"_generic",
+  //"_near",
+  //"_xdata",
+  //"_pdata",
+  //"_idata",
+  "_naked",
+  "_overlay",
+  NULL
+};
+
+
+void xa51_assignRegisters (eBBlock ** ebbs, int count);
+
+static int regParmFlg = 0;     /* determine if we can register a parameter */
+
+static void
+_xa51_init (void)
+{
+  asm_addTree (&asm_asxxxx_mapping);
+}
+
+static void
+_xa51_reset_regparm ()
+{
+  regParmFlg = 0;
+}
+
+static int
+_xa51_regparm (sym_link * l)
+{
+  return 0; // for now
+  /* for this processor it is simple
+     can pass only the first parameter in a register */
+  if (regParmFlg)
+    return 0;
+
+  regParmFlg = 1;
+  return 1;
+}
+
+static bool
+_xa51_parseOptions (int *pargc, char **argv, int *i)
+{
+  /* TODO: allow port-specific command line options to specify
+   * segment names here.
+   */
+  return FALSE;
+}
+
+static void
+_xa51_finaliseOptions (void)
+{
+  port->mem.default_local_map = istack;
+  port->mem.default_globl_map = xdata;
+}
+
+static void
+_xa51_setDefaultOptions (void)
+{
+  options.stackAuto=1;
+}
+
+static const char *
+_xa51_getRegName (struct regs *reg)
+{
+  if (reg)
+    return reg->name;
+  return "err";
+}
+
+static void
+_xa51_genAssemblerPreamble (FILE * of)
+{
+}
+
+/* Generate interrupt vector table. */
+static int
+_xa51_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
+{
+  return FALSE;
+}
+
+/* Generate code to copy XINIT to XISEG */
+static void _xa51_genXINIT (FILE * of) {
+  fprintf (of, ";      _xa51_genXINIT() start\n");
+  fprintf (of, "       mov     a,#l_XINIT\n");
+  fprintf (of, "       orl     a,#l_XINIT>>8\n");
+  fprintf (of, "       jz      00003$\n");
+  fprintf (of, "       mov     a,#s_XINIT\n");
+  fprintf (of, "       add     a,#l_XINIT\n");
+  fprintf (of, "       mov     r1,a\n");
+  fprintf (of, "       mov     a,#s_XINIT>>8\n");
+  fprintf (of, "       addc    a,#l_XINIT>>8\n");
+  fprintf (of, "       mov     r2,a\n");
+  fprintf (of, "       mov     dptr,#s_XINIT\n");
+  fprintf (of, "       mov     r0,#s_XISEG\n");
+  fprintf (of, "       mov     p2,#(s_XISEG >> 8)\n");
+  fprintf (of, "00001$:        clr     a\n");
+  fprintf (of, "       movc    a,@a+dptr\n");
+  fprintf (of, "       movx    @r0,a\n");
+  fprintf (of, "       inc     dptr\n");
+  fprintf (of, "       inc     r0\n");
+  fprintf (of, "       cjne    r0,#0,00002$\n");
+  fprintf (of, "       inc     p2\n");
+  fprintf (of, "00002$:        mov     a,dpl\n");
+  fprintf (of, "       cjne    a,ar1,00001$\n");
+  fprintf (of, "       mov     a,dph\n");
+  fprintf (of, "       cjne    a,ar2,00001$\n");
+  fprintf (of, "       mov     p2,#0xFF\n");
+  fprintf (of, "00003$:\n");
+  fprintf (of, ";      _xa51_genXINIT() end\n");
+}
+
+
+/* Do CSE estimation */
+static bool cseCostEstimation (iCode *ic, iCode *pdic)
+{
+    operand *result = IC_RESULT(ic);
+    sym_link *result_type = operandType(result);
+
+    /* if it is a pointer then return ok for now */
+    if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
+    
+    /* if bitwise | add & subtract then no since xa51 is pretty good at it 
+       so we will cse only if they are local (i.e. both ic & pdic belong to
+       the same basic block */
+    if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
+       /* then if they are the same Basic block then ok */
+       if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
+       else return 0;
+    }
+       
+    /* for others it is cheaper to do the cse */
+    return 1;
+}
+
+/** $1 is always the basename.
+    $2 is always the output file.
+    $3 varies
+    $l is the list of extra options that should be there somewhere...
+    MUST be terminated with a NULL.
+*/
+static const char *_linkCmd[] =
+{
+  "{bindir}{sep}aslink", "-nf", "$1", NULL
+};
+
+/* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
+static const char *_asmCmd[] =
+{
+  "xa_asm", "$l", "$3", "$1.asm", NULL
+};
+
+/* Globals */
+PORT xa51_port =
+{
+  TARGET_ID_XA51,
+  "xa51",
+  "MCU 80C51XA",                       /* Target name */
+  {
+    TRUE,                      /* Emit glue around main */
+    MODEL_LARGE,
+    MODEL_LARGE
+  },
+  {
+    _asmCmd,
+    NULL,
+    "-plosgffc",               /* Options with debug */
+    "-plosgff",                        /* Options without debug */
+    0,
+    ".asm",
+    NULL                       /* no do_assemble function */
+  },
+  {
+    _linkCmd,
+    NULL,
+    NULL,
+    ".rel"
+  },
+  {
+    _defaultRules
+  },
+  {
+       /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
+    1, 2, 2, 4, 1, 2, 3, 1, 4, 4
+  },
+  {
+    "XSEG    (XDATA)",
+    "STACK   (DATA)",
+    "CSEG    (CODE)",
+    "DSEG    (DATA)",
+    "ISEG    (DATA)",
+    "XSEG    (XDATA)",
+    "BSEG    (BIT)",
+    "RSEG    (DATA)",
+    "GSINIT  (CODE)",
+    "OSEG    (OVR,DATA)",
+    "GSFINAL (CODE)",
+    "HOME    (CODE)",
+    "XISEG   (XDATA)", // initialized xdata
+    "XINIT   (CODE)", // a code copy of xiseg
+    NULL, // default local map
+    NULL, // default global map
+    1
+  },
+  {
+    -1, // stack grows down
+    0, // bank overhead NUY
+    6, // isr overhead
+    4, // function call overhead
+    0, // reentrant overhead NUY
+    0 // banked overhead NUY
+  },
+    /* xa51 has an 16 bit mul */
+  {
+    2, -2
+  },
+  "_",
+  _xa51_init,
+  _xa51_parseOptions,
+  _xa51_finaliseOptions,
+  _xa51_setDefaultOptions,
+  xa51_assignRegisters,
+  _xa51_getRegName,
+  _xa51_keywords,
+  _xa51_genAssemblerPreamble,
+  NULL,                                /* no genAssemblerEnd */
+  _xa51_genIVT,
+  _xa51_genXINIT,
+  _xa51_reset_regparm,
+  _xa51_regparm,
+  NULL,
+  NULL,
+  NULL,
+  FALSE,
+  0,                           /* leave lt */
+  0,                           /* leave gt */
+  1,                           /* transform <= to ! > */
+  1,                           /* transform >= to ! < */
+  1,                           /* transform != to !(a == b) */
+  0,                           /* leave == */
+  FALSE,                        /* No array initializer support. */
+  cseCostEstimation,
+  NULL,                        /* no builtin functions */
+  GPOINTER,                    /* treat unqualified pointers as "generic" pointers */
+  1,                           /* reset labelKey to 1 */
+  1,                           /* globals & local static allowed */
+  PORT_MAGIC
+};
diff --git a/src/xa51/main.h b/src/xa51/main.h
new file mode 100644 (file)
index 0000000..6555225
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef MAIN_INCLUDE
+#define MAIN_INCLUDE
+
+bool x_parseOptions (char **argv, int *pargc);
+void x_setDefaultOptions (void);
+void x_finaliseOptions (void);
+
+#endif
diff --git a/src/xa51/main.o b/src/xa51/main.o
new file mode 100644 (file)
index 0000000..305d8cd
Binary files /dev/null and b/src/xa51/main.o differ
diff --git a/src/xa51/peeph.def b/src/xa51/peeph.def
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/xa51/peeph.rul b/src/xa51/peeph.rul
new file mode 100644 (file)
index 0000000..7e86f10
--- /dev/null
@@ -0,0 +1,3 @@
+/* Generated file, DO NOT Edit!  */
+/* To Make changes to rules edit */
+/* <port>/peeph.def instead.     */
diff --git a/src/xa51/port.a b/src/xa51/port.a
new file mode 100644 (file)
index 0000000..5d6cc01
Binary files /dev/null and b/src/xa51/port.a differ
diff --git a/src/xa51/ralloc.c b/src/xa51/ralloc.c
new file mode 100755 (executable)
index 0000000..abd08af
--- /dev/null
@@ -0,0 +1,2163 @@
+/*------------------------------------------------------------------------
+
+  SDCCralloc.c - source file for register allocation. (xa51) specific
+
+                Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!  
+-------------------------------------------------------------------------*/
+
+#include "common.h"
+#include "ralloc.h"
+#include "gen.h"
+
+/*-----------------------------------------------------------------*/
+/* At this point we start getting processor specific although      */
+/* some routines are non-processor specific & can be reused when   */
+/* targetting other processors. The decision for this will have    */
+/* to be made on a routine by routine basis                        */
+/* routines used to pack registers are most definitely not reusable */
+/* since the pack the registers depending strictly on the MCU      */
+/*-----------------------------------------------------------------*/
+
+extern void genXA51Code (iCode *);
+#define D(x)
+
+/* Global data */
+static struct
+  {
+    bitVect *spiltSet;
+    set *stackSpil;
+    bitVect *regAssigned;
+    bitVect *totRegAssigned;    /* final set of LRs that got into registers */
+    short blockSpil;
+    int slocNum;
+    bitVect *funcrUsed;                /* registers used in a function */
+    int stackExtend;
+    int dataExtend;
+  }
+_G;
+
+/* xa51 registers */
+regs regsXA51[]={
+  // index size type name regMask offset isFree symbol
+  {0x20, 2, REG_SCR, "r0",  0x0003, 0, 1, NULL}, // r0 used for scratch
+  {0x21, 2, REG_SCR, "r1",  0x000c, 2, 1, NULL}, // r1 used for scratch
+  {0x22, 2, REG_PTR, "r2",  0x0030, 4, 1, NULL}, 
+  {0x23, 2, REG_PTR, "r3",  0x00c0, 6, 1, NULL},
+  {0x24, 2, REG_PTR, "r4",  0x0300, 8, 1, NULL}, 
+  {0x25, 2, REG_PTR, "r5",  0x0c00, 10, 1, NULL}, 
+  {0x26, 2, REG_PTR, "r6",  0x3000, 12, 1, NULL}, 
+  {0x27, 2, REG_STK, "r7",  0xc000, 14, 1, NULL}, // r7=SP
+#if 0 // some derivates have even more! (only word access and gpr use)
+  {0x28, 2, REG_GPR, "r8",  0x10000, 16, 1, NULL},
+  {0x29, 2, REG_GPR, "r9",  0x20000, 18, 1, NULL},
+  {0x2a, 2, REG_GPR, "r10", 0x40000, 20, 1, NULL},
+  {0x2b, 2, REG_GPR, "r11", 0x80000, 22, 1, NULL},
+  {0x2c, 2, REG_GPR, "r12", 0x100000, 24, 1, NULL},
+  {0x2d, 2, REG_GPR, "r13", 0x200000, 26, 1, NULL},
+  {0x2e, 2, REG_GPR, "r14", 0x400000, 28, 1, NULL},
+  {0x2f, 2, REG_GPR, "r15", 0x800000, 20, 1, NULL},
+#endif
+  {0x10, 1, REG_SCR, "r0h", 0x0001, 1, 1, NULL}, // r0h used for scratch
+  {0x11, 1, REG_SCR, "r0l", 0x0002, 1, 1, NULL}, // r0l used for scratch
+  {0x12, 1, REG_SCR, "r1h", 0x0004, 2, 1, NULL}, // r1h used for scratch
+  {0x13, 1, REG_SCR, "r1l", 0x0008, 3, 1, NULL}, // r1l used for scratch
+  {0x14, 1, REG_PTR, "r2h", 0x0010, 4, 1, NULL},
+  {0x15, 1, REG_PTR, "r2l", 0x0020, 5, 1, NULL},
+  {0x16, 1, REG_PTR, "r3h", 0x0040, 6, 1, NULL},
+  {0x17, 1, REG_PTR, "r3l", 0x0080, 7, 1, NULL},
+  {0x18, 1, REG_PTR, "r4h", 0x0100, 8, 1, NULL},
+  {0x19, 1, REG_PTR, "r4l", 0x0200, 9, 1, NULL},
+  {0x1a, 1, REG_PTR, "r5h", 0x0400, 10, 1, NULL},
+  {0x1b, 1, REG_PTR, "r5l", 0x0800, 11, 1, NULL},
+  {0x1c, 1, REG_PTR, "r6h", 0x1000, 12, 1, NULL},
+  {0x1d, 1, REG_PTR, "r6l", 0x2000, 13, 1, NULL},
+  {0x1e, 1, REG_STK, "r7h", 0x4000, 14, 1, NULL}, // r7=SP
+  {0x1f, 1, REG_STK, "r7l", 0x8000, 15, 1, NULL}, // r7=SP
+};
+
+int xa51_nRegs=sizeof(regsXA51)/sizeof(regs);
+
+udword xa51RegsInUse=0;
+
+// this should be set with a command line switch
+bool xa51HasGprRegs=0;
+
+/*-----------------------------------------------------------------*/
+/* xa51_regWithMask - returns pointer to register with mask        */
+/*-----------------------------------------------------------------*/
+regs *xa51_regWithMask (udword mask) {
+  int i;
+  for (i=0; i<xa51_nRegs; i++) {
+    if (regsXA51[i].regMask==mask) {
+      return &regsXA51[i];
+    }
+  }
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* checkRegsMask - check the consistancy of the regMask redundancy */
+/*-----------------------------------------------------------------*/
+
+void checkRegMask(char *f) { // for debugging purposes only
+  int i;
+  udword regMask=0;
+
+  for (i=0; i<xa51_nRegs; i++) {
+    if (!regsXA51[i].isFree) {
+      regMask |= regsXA51[i].regMask;
+    }
+  }
+
+  if (regMask != xa51RegsInUse) {
+    fprintf (stderr, "error(%s): regMask inconsistent 0x%08x != 0x%08x\n",
+            f, regMask, xa51RegsInUse);
+    regMask=regMask^xa51RegsInUse;
+    fprintf (stderr, "%s used by %s\n", 
+            xa51_regWithMask(regMask)->name, 
+            xa51_regWithMask(regMask)->sym->name);
+    
+    exit(1);
+    return;
+  }
+}
+    
+char *regTypeToStr(short type) {
+  switch (type) 
+    {
+    case REG_PTR: return "ptr"; break; // pointer
+    case REG_GPR: return "gpr"; break; // general purpose
+    case REG_CND: return "cnd"; break; // condition (bit)
+    case REG_STK: return "stk"; break; // stack
+    case REG_SCR: return "scr"; break; // scratch
+    default: return "???"; break;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* freeReg - frees a previous allocated register                   */
+/*-----------------------------------------------------------------*/
+static void freeReg (regs * reg, bool silent) {
+
+  checkRegMask(__FUNCTION__);
+
+  if (!reg) {
+    werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+           "freeReg - freeing NULL register");
+    return;
+  }
+  
+  if (!silent) {
+    fprintf (stderr, "freeReg: (%08x) %s ", xa51RegsInUse, reg->name);
+  }
+
+  if (reg->isFree || ((xa51RegsInUse&reg->regMask)!=reg->regMask)) {
+    werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+           "freeReg - freeing unused register(s)");
+    return;
+  }
+  xa51RegsInUse &= ~reg->regMask;
+  reg->isFree = 1;
+  reg->sym = NULL;
+  if (!silent) fprintf (stderr, "(%08x)\n", xa51RegsInUse);
+
+  checkRegMask(__FUNCTION__);
+}
+
+/*-----------------------------------------------------------------*/
+/* allocReg - allocates register of given size (byte, word)        */
+/*            and type (ptr, gpr, cnd)                             */
+/*-----------------------------------------------------------------*/
+static bool allocReg (short size, short type, symbol *sym, 
+                     short offset, bool silent) {
+  int i;
+
+  checkRegMask(__FUNCTION__);
+
+  if (!silent) {
+    fprintf (stderr, "allocReg (0x%08x) for %s size:%d, type:%s ", 
+            xa51RegsInUse,
+            sym->name,
+            size, regTypeToStr(type));
+  }
+
+  switch (size) 
+    {
+      // TODO: gaps should be filled for dwords too
+    case 1:
+      // let's see if we can fill a gap
+      for (i=0; i<xa51_nRegs; i++) {
+       if (regsXA51[i].size==2 && regsXA51[i].type==type) {
+         udword mask=regsXA51[i].regMask & ~xa51RegsInUse;
+         if (mask && mask!=regsXA51[i].regMask) {
+           regs *reg=xa51_regWithMask(mask);
+           // found a gap
+           sym->regs[offset]=reg;
+           xa51RegsInUse |= mask;
+           reg->isFree=0; // redundant
+           reg->sym = sym;
+           if (!silent) {
+             fprintf (stderr, "(using gap) %s\n", reg->name);
+           }
+           checkRegMask(__FUNCTION__);
+           return TRUE;
+         }
+       }
+      }
+      // no we can't, fall through
+    case 2:
+      for (i=0; i<xa51_nRegs; i++) {
+       if (regsXA51[i].size==size &&
+           regsXA51[i].type==type &&
+           (regsXA51[i].regMask & xa51RegsInUse)==0) {
+         xa51RegsInUse |= regsXA51[i].regMask;
+         regsXA51[i].isFree = 0; // redundant
+         regsXA51[i].sym = sym;
+         if (!silent) {
+           fprintf (stderr, "%s\n", regsXA51[i].name);
+         }
+         sym->regs[offset]=&regsXA51[i];
+         checkRegMask(__FUNCTION__);
+         return TRUE;
+       }
+      }
+      if (!silent) {
+       fprintf (stderr, "failed (%08x)\n", xa51RegsInUse);
+      }
+      checkRegMask(__FUNCTION__);
+      return FALSE;
+      break;
+    case 3:
+      // this must be a generic pointer
+      if (!silent) {
+       fprintf (stderr, "trying 2+1\n");
+      }
+      // get the pointer part
+      if (allocReg (2, REG_PTR, sym, offset, silent)) {
+       // get the generic part
+       if ((xa51HasGprRegs && allocReg (1, REG_GPR, sym, offset+1, silent)) ||
+           allocReg (1, REG_PTR, sym, offset+1, silent)) {
+         checkRegMask(__FUNCTION__);
+         return TRUE;
+       }
+       freeReg(sym->regs[offset], silent);
+       sym->regs[offset]=NULL;
+      }
+      checkRegMask(__FUNCTION__);
+      return FALSE;
+      break;
+    case 4: // this is a dword
+      if (!silent) {
+       fprintf (stderr, "trying 2+2\n");
+      }
+      if ((xa51HasGprRegs && allocReg (2, REG_GPR, sym, offset, silent)) ||
+         allocReg (2, REG_PTR, sym, offset, silent)) {
+       if ((xa51HasGprRegs && allocReg (2, REG_GPR, sym, offset+1, silent)) ||
+           allocReg (2, REG_PTR, sym, offset+1, silent)) {
+         checkRegMask(__FUNCTION__);
+         return TRUE;
+       }
+      }
+      freeReg(sym->regs[offset], FALSE);
+      sym->regs[offset]=NULL;
+      checkRegMask(__FUNCTION__);
+      return FALSE;
+      break;
+    default:
+      fprintf (stderr, "\nallocReg: cannot allocate reg of size %d\n", size);
+      exit (1);
+      break;
+    }
+  // we should never come here
+  return FALSE;
+}
+
+/*-------------------------------------------------------------------*/
+/* freeAllRegs - frees all registers                                 */
+/*-------------------------------------------------------------------*/
+// just to be sure, this should not be needed
+static void freeAllRegs (void) {
+  char regsFreed[132];
+  int i;
+  int nfr = 0;
+  
+  checkRegMask(__FUNCTION__);
+
+  regsFreed[0]=0;
+  for (i=0; i<xa51_nRegs; i++) {
+    if (!regsXA51[i].isFree) {
+      strcat (regsFreed, regsXA51[i].name);
+      strcat (regsFreed, " ");
+      regsXA51[i].isFree=1;
+      regsXA51[i].sym=NULL;
+      nfr++;
+    }
+  }
+  xa51RegsInUse=0;
+  if (nfr) {
+    fprintf (stderr, "freeAllRegisters: %d regs freed (%s)\n", nfr, regsFreed);
+    exit (1);
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/* allDefsOutOfRange - all definitions are out of a range          */
+/*-----------------------------------------------------------------*/
+static bool allDefsOutOfRange (bitVect * defs, int fseq, int toseq) {
+  int i;
+
+  if (!defs)
+    return TRUE;
+
+  for (i = 0; i < defs->size; i++)
+    {
+      iCode *ic;
+
+      if (bitVectBitValue (defs, i) &&
+         (ic = hTabItemWithKey (iCodehTab, i)) &&
+         (ic->seq >= fseq && ic->seq <= toseq))
+       return FALSE;
+    }
+  return TRUE;
+}
+
+/*-----------------------------------------------------------------*/
+/* computeSpillable - given a point find the spillable live ranges */
+/*-----------------------------------------------------------------*/
+static bitVect *computeSpillable (iCode * ic) {
+  bitVect *spillable;
+
+  /* spillable live ranges are those that are live at this 
+     point . the following categories need to be subtracted
+     from this set. 
+     a) - those that are already spilt
+     b) - if being used by this one
+     c) - defined by this one */
+
+  spillable = bitVectCopy (ic->rlive);
+  spillable =
+    bitVectCplAnd (spillable, _G.spiltSet);    /* those already spilt */
+  spillable =
+    bitVectCplAnd (spillable, ic->uses);       /* used in this one */
+  bitVectUnSetBit (spillable, ic->defKey);      /* defined by this one */
+  spillable = bitVectIntersect (spillable, _G.regAssigned);
+  return spillable;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* noSpilLoc - return true if a variable has no spil location      */
+/*-----------------------------------------------------------------*/
+static int
+noSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  return (sym->usl.spillLoc ? 0 : 1);
+}
+
+/*-----------------------------------------------------------------*/
+/* hasSpilLoc - will return 1 if the symbol has spil location      */
+/*-----------------------------------------------------------------*/
+static int
+hasSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  return (sym->usl.spillLoc ? 1 : 0);
+}
+
+/*-----------------------------------------------------------------*/
+/* hasSpilLocnoUptr - will return 1 if the symbol has spil location */
+/*                    but is not used as a pointer                 */
+/*-----------------------------------------------------------------*/
+static int
+hasSpilLocnoUptr (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  return ((sym->usl.spillLoc && !sym->uptr) ? 1 : 0);
+}
+
+/*-----------------------------------------------------------------*/
+/* rematable - will return 1 if the remat flag is set              */
+/*-----------------------------------------------------------------*/
+static int
+rematable (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  return sym->remat;
+}
+
+/*-----------------------------------------------------------------*/
+/* notUsedInBlock - not used in this block                         */
+/*-----------------------------------------------------------------*/
+static int
+notUsedInBlock (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  return (!bitVectBitsInCommon (sym->defs, ebp->usesDefs) &&
+         allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
+/*     return (!bitVectBitsInCommon(sym->defs,ebp->usesDefs)); */
+}
+
+/*-----------------------------------------------------------------*/
+/* notUsedInRemaining - not used or defined in remain of the block */
+/*-----------------------------------------------------------------*/
+static int
+notUsedInRemaining (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  return ((usedInRemaining (operandFromSymbol (sym), ic) ? 0 : 1) &&
+         allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
+}
+
+/*-----------------------------------------------------------------*/
+/* allLRs - return true for all                                    */
+/*-----------------------------------------------------------------*/
+static int
+allLRs (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* liveRangesWith - applies function to a given set of live range  */
+/*-----------------------------------------------------------------*/
+static set *
+liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
+               eBBlock * ebp, iCode * ic)
+{
+  set *rset = NULL;
+  int i;
+
+  if (!lrs || !lrs->size)
+    return NULL;
+
+  for (i = 1; i < lrs->size; i++)
+    {
+      symbol *sym;
+      if (!bitVectBitValue (lrs, i))
+       continue;
+
+      /* if we don't find it in the live range 
+         hash table we are in serious trouble */
+      if (!(sym = hTabItemWithKey (liveRanges, i)))
+       {
+         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                 "liveRangesWith could not find liveRange");
+         exit (1);
+       }
+
+      if (func (sym, ebp, ic) && bitVectBitValue (_G.regAssigned, sym->key))
+       addSetHead (&rset, sym);
+    }
+
+  return rset;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* leastUsedLR - given a set determines which is the least used    */
+/*-----------------------------------------------------------------*/
+static symbol *
+leastUsedLR (set * sset)
+{
+  symbol *sym = NULL, *lsym = NULL;
+
+  sym = lsym = setFirstItem (sset);
+
+  if (!lsym)
+    return NULL;
+
+  for (; lsym; lsym = setNextItem (sset))
+    {
+
+      /* if usage is the same then prefer
+         the spill the smaller of the two */
+      if (lsym->used == sym->used)
+       if (getSize (lsym->type) < getSize (sym->type))
+         sym = lsym;
+
+      /* if less usage */
+      if (lsym->used < sym->used)
+       sym = lsym;
+
+    }
+
+  setToNull ((void **) &sset);
+  sym->blockSpil = 0;
+  return sym;
+}
+
+/*-----------------------------------------------------------------*/
+/* noOverLap - will iterate through the list looking for over lap  */
+/*-----------------------------------------------------------------*/
+static int
+noOverLap (set * itmpStack, symbol * fsym)
+{
+  symbol *sym;
+
+
+  for (sym = setFirstItem (itmpStack); sym;
+       sym = setNextItem (itmpStack))
+    {
+       if (bitVectBitValue(sym->clashes,fsym->key)) return 0;
+    }
+
+  return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* isFree - will return 1 if the a free spil location is found     */
+/*-----------------------------------------------------------------*/
+static
+DEFSETFUNC (isFree)
+{
+  symbol *sym = item;
+  V_ARG (symbol **, sloc);
+  V_ARG (symbol *, fsym);
+
+  /* if already found */
+  if (*sloc)
+    return 0;
+
+  /* if it is free && and the itmp assigned to
+     this does not have any overlapping live ranges
+     with the one currently being assigned and
+     the size can be accomodated  */
+  if (sym->isFree &&
+      noOverLap (sym->usl.itmpStack, fsym) &&
+      getSize (sym->type) >= getSize (fsym->type))
+    {
+      *sloc = sym;
+      return 1;
+    }
+
+  return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* createStackSpil - create a location on the stack to spil        */
+/*-----------------------------------------------------------------*/
+static symbol *
+createStackSpil (symbol * sym)
+{
+  symbol *sloc = NULL;
+  int useXstack, model;
+
+  char slocBuffer[30];
+
+  fprintf (stderr, "  createStackSpil: %s\n", sym->name);
+
+  /* first go try and find a free one that is already 
+     existing on the stack */
+  if (applyToSet (_G.stackSpil, isFree, &sloc, sym))
+    {
+      /* found a free one : just update & return */
+      sym->usl.spillLoc = sloc;
+      sym->stackSpil = 1;
+      sloc->isFree = 0;
+      addSetHead (&sloc->usl.itmpStack, sym);
+      return sym;
+    }
+
+  /* could not then have to create one , this is the hard part
+     we need to allocate this on the stack : this is really a
+     hack!! but cannot think of anything better at this time */
+
+  if (sprintf (slocBuffer, "sloc%d", _G.slocNum++) >= sizeof (slocBuffer))
+    {
+      fprintf (stderr, "***Internal error: slocBuffer overflowed: %s:%d\n",
+              __FILE__, __LINE__);
+      exit (1);
+    }
+
+  sloc = newiTemp (slocBuffer);
+
+  /* set the type to the spilling symbol */
+  sloc->type = copyLinkChain (sym->type);
+  sloc->etype = getSpec (sloc->type);
+  SPEC_SCLS (sloc->etype) = S_STACK;
+  SPEC_EXTR (sloc->etype) = 0;
+  SPEC_STAT (sloc->etype) = 0;
+  SPEC_VOLATILE(sloc->etype) = 0;
+  SPEC_ABSA(sloc->etype) = 0;
+
+  /* we don't allow it to be allocated`
+     onto the external stack since : so we
+     temporarily turn it off ; we also
+     turn off memory model to prevent
+     the spil from going to the external storage
+   */
+
+  useXstack = options.useXstack;
+  model = options.model;
+/*     noOverlay = options.noOverlay; */
+/*     options.noOverlay = 1; */
+  options.model = options.useXstack = 0;
+
+  allocLocal (sloc);
+
+  options.useXstack = useXstack;
+  options.model = model;
+/*     options.noOverlay = noOverlay; */
+  sloc->isref = 1;             /* to prevent compiler warning */
+
+  /* if it is on the stack then update the stack */
+  if (IN_STACK (sloc->etype))
+    {
+      currFunc->stack += getSize (sloc->type);
+      _G.stackExtend += getSize (sloc->type);
+    }
+  else
+    _G.dataExtend += getSize (sloc->type);
+
+  /* add it to the _G.stackSpil set */
+  addSetHead (&_G.stackSpil, sloc);
+  sym->usl.spillLoc = sloc;
+  sym->stackSpil = 1;
+
+  /* add it to the set of itempStack set 
+     of the spill location */
+  addSetHead (&sloc->usl.itmpStack, sym);
+  return sym;
+}
+
+/*-----------------------------------------------------------------*/
+/* spillThis - spils a specific operand                            */
+/*-----------------------------------------------------------------*/
+static void
+spillThis (symbol * sym)
+{
+  int i;
+  
+  fprintf (stderr, "  spillThis: %s\n", sym->name);
+
+  /* if this is rematerializable or has a spillLocation
+     we are okay, else we need to create a spillLocation
+     for it */
+  if (!(sym->remat || sym->usl.spillLoc))
+    createStackSpil (sym);
+
+
+  /* mark it has spilt & put it in the spilt set */
+  sym->isspilt = sym->spillA = 1;
+  _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
+
+  bitVectUnSetBit (_G.regAssigned, sym->key);
+  bitVectUnSetBit (_G.totRegAssigned, sym->key);
+
+  for (i = 0; i < sym->nRegs; i++)
+
+    if (sym->regs[i])
+      {
+       freeReg (sym->regs[i], FALSE);
+      }
+
+  if (sym->usl.spillLoc && !sym->remat)
+    sym->usl.spillLoc->allocreq++;
+  return;
+}
+
+/*-----------------------------------------------------------------*/
+/* selectSpil - select a iTemp to spil : rather a simple procedure */
+/*-----------------------------------------------------------------*/
+static symbol *
+selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
+{
+  bitVect *lrcs = NULL;
+  set *selectS;
+  symbol *sym;
+
+  /* get the spillable live ranges */
+  lrcs = computeSpillable (ic);
+
+  /* get all live ranges that are rematerizable */
+  if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic)))
+    {
+      /* return the least used of these */
+      return leastUsedLR (selectS);
+    }
+
+  /* if the symbol is local to the block then */
+  if (forSym->liveTo < ebp->lSeq)
+    {
+
+      /* check if there are any live ranges allocated
+         to registers that are not used in this block */
+      if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInBlock, ebp, ic)))
+       {
+         sym = leastUsedLR (selectS);
+         /* if this is not rematerializable */
+         if (!sym->remat)
+           {
+             _G.blockSpil++;
+             sym->blockSpil = 1;
+           }
+         return sym;
+       }
+
+      /* check if there are any live ranges that not
+         used in the remainder of the block */
+      if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
+       {
+         sym = leastUsedLR (selectS);
+         if (sym != forSym)
+           {
+             if (!sym->remat)
+               {
+                 sym->remainSpil = 1;
+                 _G.blockSpil++;
+               }
+             return sym;
+           }
+       }
+    }
+
+  /* find live ranges with spillocation && not used as pointers */
+  if ((selectS = liveRangesWith (lrcs, hasSpilLocnoUptr, ebp, ic)))
+    {
+
+      sym = leastUsedLR (selectS);
+      /* mark this as allocation required */
+      sym->usl.spillLoc->allocreq++;
+      return sym;
+    }
+
+  /* find live ranges with spillocation */
+  if ((selectS = liveRangesWith (lrcs, hasSpilLoc, ebp, ic)))
+    {
+
+      sym = leastUsedLR (selectS);
+      sym->usl.spillLoc->allocreq++;
+      return sym;
+    }
+
+  /* couldn't find then we need to create a spil
+     location on the stack , for which one? the least
+     used ofcourse */
+  if ((selectS = liveRangesWith (lrcs, noSpilLoc, ebp, ic)))
+    {
+
+      /* return a created spil location */
+      sym = createStackSpil (leastUsedLR (selectS));
+      sym->usl.spillLoc->allocreq++;
+      return sym;
+    }
+
+  /* this is an extreme situation we will spill
+     this one : happens very rarely but it does happen */
+  spillThis (forSym);
+  return forSym;
+}
+
+/*-----------------------------------------------------------------*/
+/* spillSomething - spil some variable & mark registers as free    */
+/*-----------------------------------------------------------------*/
+static bool
+spillSomething (iCode * ic, eBBlock * ebp, symbol * forSym)
+{
+  symbol *ssym;
+  int i;
+
+  /* get something we can spil */
+  ssym = selectSpil (ic, ebp, forSym);
+
+  fprintf (stderr, "  spillSomething: spilling %s\n", ssym->name);
+
+  /* mark it as spilt */
+  ssym->isspilt = ssym->spillA = 1;
+  _G.spiltSet = bitVectSetBit (_G.spiltSet, ssym->key);
+
+  /* mark it as not register assigned &
+     take it away from the set */
+  bitVectUnSetBit (_G.regAssigned, ssym->key);
+  bitVectUnSetBit (_G.totRegAssigned, ssym->key);
+
+  /* mark the registers as free */
+  for (i = 0; i < ssym->nRegs; i++) {
+    if (ssym->regs[i]) {
+      freeReg (ssym->regs[i], FALSE);
+      // dont NULL ssym->regs[i], it might be used later
+    }
+  }
+
+  /* if this was a block level spil then insert push & pop 
+     at the start & end of block respectively */
+  if (ssym->blockSpil)
+    {
+      iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
+      /* add push to the start of the block */
+      addiCodeToeBBlock (ebp, nic, (ebp->sch->op == LABEL ?
+                                   ebp->sch->next : ebp->sch));
+      nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
+      /* add pop to the end of the block */
+      addiCodeToeBBlock (ebp, nic, NULL);
+    }
+
+  /* if spilt because not used in the remainder of the
+     block then add a push before this instruction and
+     a pop at the end of the block */
+  if (ssym->remainSpil)
+    {
+
+      iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
+      /* add push just before this instruction */
+      addiCodeToeBBlock (ebp, nic, ic);
+
+      nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
+      /* add pop to the end of the block */
+      addiCodeToeBBlock (ebp, nic, NULL);
+    }
+
+  if (ssym == forSym)
+    return FALSE;
+  else
+    return TRUE;
+}
+
+/*-----------------------------------------------------------------*/
+/* getRegPtr - will try for PTR if not a GPR type if not spil      */
+/*-----------------------------------------------------------------*/
+static bool getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym, short offset) {
+
+  fprintf (stderr, "getRegPtr: %s ", sym->name);
+  printTypeChain(sym->type, stderr);
+  fprintf (stderr, "\n");
+
+tryAgain:
+  /* try for a ptr type */
+  if (allocReg (getSize(sym->type), REG_PTR, sym, offset, FALSE))
+    return TRUE;
+
+  /* try for gpr type */
+  if (xa51HasGprRegs && allocReg (getSize(sym->type), 
+                                 REG_GPR, sym, offset, FALSE))
+    return TRUE;
+
+  /* we have to spil */
+  if (!spillSomething (ic, ebp, sym))
+    return FALSE;
+
+  /* this looks like an infinite loop but 
+     in really selectSpil will abort  */
+  goto tryAgain;
+}
+
+/*-----------------------------------------------------------------*/
+/* getRegGpr - will try for GPR if not spil                        */
+/*-----------------------------------------------------------------*/
+static bool getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym, short offset) {
+
+  fprintf (stderr, "getRegGpr: %s ", sym->name);
+  printTypeChain(sym->type, stderr);
+  fprintf (stderr, "\n");
+
+tryAgain:
+  /* try for gpr type */
+  if (xa51HasGprRegs && allocReg (getSize(sym->type), 
+                                 REG_GPR, sym, offset, FALSE))
+    return TRUE;
+
+  if (allocReg (getSize(sym->type), REG_PTR, sym, offset, FALSE))
+    return TRUE;
+
+  /* we have to spil */
+  if (!spillSomething (ic, ebp, sym))
+    return FALSE;
+
+  /* this looks like an infinite loop but 
+     in really selectSpil will abort  */
+  goto tryAgain;
+}
+
+/*-----------------------------------------------------------------*/
+/* deassignLRs - check the live to and if they have registers & are */
+/*               not spilt then free up the registers              */
+/*-----------------------------------------------------------------*/
+static void
+deassignLRs (iCode * ic, eBBlock * ebp)
+{
+  symbol *sym;
+  int k;
+
+  for (sym = hTabFirstItem (liveRanges, &k); sym;
+       sym = hTabNextItem (liveRanges, &k))
+    {
+      /* if it does not end here */
+      if (sym->liveTo > ic->seq)
+       continue;
+      
+      /* if it was spilt on stack then we can 
+         mark the stack spil location as free */
+      if (sym->isspilt)
+       {
+         if (sym->stackSpil)
+           {
+             sym->usl.spillLoc->isFree = 1;
+             sym->stackSpil = 0;
+           }
+         continue;
+       }
+      
+      if (!bitVectBitValue (_G.regAssigned, sym->key))
+       continue;
+      
+      if (sym->nRegs) {
+       int i;
+       
+       bitVectUnSetBit (_G.regAssigned, sym->key);
+       
+       /* free the regs */
+       for (i=0; i < sym->nRegs; i++) {
+         freeReg (sym->regs[i], FALSE);
+       }
+      }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* willCauseSpill - determines if allocating will cause a spill    */
+/*-----------------------------------------------------------------*/
+static bool willCauseSpill (symbol *sym) {
+  int i;
+  // do it the rude way
+  if (allocReg (getSize(sym->type), sym->regType, sym, 0, TRUE) ||
+      allocReg (getSize(sym->type), sym->regType==REG_PTR?REG_GPR:REG_PTR, 
+               sym, 0, TRUE)) {
+    // so we can, but we won't
+    for (i=0; i<sym->nRegs; i++) {
+      freeReg (sym->regs[i], TRUE);
+      sym->regs[i]=NULL;
+    }
+    return FALSE;
+  }
+  fprintf (stderr, "  %s will cause a spill\n", sym->name);
+  return TRUE;
+}
+
+/*-----------------------------------------------------------------*/
+/* positionRegs - the allocator can allocate same registers to res- */
+/* ult and operand, if this happens make sure they are in the same */
+/* position as the operand otherwise chaos results                 */
+/*-----------------------------------------------------------------*/
+static int
+positionRegs (symbol * result, symbol * opsym)
+{
+  int count = min (result->nRegs, opsym->nRegs);
+  int i, j = 0, shared = 0;
+  int change = 0;
+
+  /* if the result has been spilt then cannot share */
+  if (opsym->isspilt)
+    return 0;
+again:
+  shared = 0;
+  /* first make sure that they actually share */
+  for (i = 0; i < count; i++)
+    {
+      for (j = 0; j < count; j++)
+       {
+         if (result->regs[i] == opsym->regs[j] && i != j)
+           {
+             shared = 1;
+             goto xchgPositions;
+           }
+       }
+    }
+xchgPositions:
+  if (shared)
+    {
+      regs *tmp = result->regs[i];
+      result->regs[i] = result->regs[j];
+      result->regs[j] = tmp;
+      change ++;
+      goto again;
+    }
+  return change;
+}
+
+/*-----------------------------------------------------------------*/
+/* serialRegAssign - serially allocate registers to the variables  */
+/*-----------------------------------------------------------------*/
+static void
+serialRegAssign (eBBlock ** ebbs, int count)
+{
+    int i;
+
+    /* for all blocks */
+    for (i = 0; i < count; i++) {
+
+       iCode *ic;
+
+       if (ebbs[i]->noPath &&
+           (ebbs[i]->entryLabel != entryLabel &&
+            ebbs[i]->entryLabel != returnLabel))
+           continue;
+
+       /* of all instructions do */
+       for (ic = ebbs[i]->sch; ic; ic = ic->next) {
+
+           /* if result is present && is a true symbol */
+           if (IC_RESULT (ic) && ic->op != IFX &&
+               IS_TRUE_SYMOP (IC_RESULT (ic)))
+               OP_SYMBOL (IC_RESULT (ic))->allocreq++;
+
+           /* take away registers from live
+              ranges that end at this instruction */
+           deassignLRs (ic, ebbs[i]);
+
+           /* some don't need registers */
+           if (SKIP_IC2 (ic) ||
+               ic->op == JUMPTABLE ||
+               ic->op == IFX ||
+               ic->op == IPUSH ||
+               ic->op == IPOP ||
+               (IC_RESULT (ic) && POINTER_SET (ic)))
+               continue;
+
+           /* now we need to allocate registers
+              only for the result */
+           if (IC_RESULT (ic)) {
+               symbol *sym = OP_SYMBOL (IC_RESULT (ic));
+               bitVect *spillable;
+               int willCS;
+
+               /* if it does not need or is spilt 
+                  or is already assigned to registers
+                  or will not live beyond this instructions */
+               if (!sym->nRegs ||
+                   sym->isspilt ||
+                   bitVectBitValue (_G.regAssigned, sym->key) ||
+                   sym->liveTo <= ic->seq)
+                   continue;
+
+               /* if some liverange has been spilt at the block level
+                  and this one live beyond this block then spil this
+                  to be safe */
+               if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq) {
+                   spillThis (sym);
+                   continue;
+               }
+               /* if trying to allocate this will cause
+                  a spill and there is nothing to spill 
+                  or this one is rematerializable then
+                  spill this one */
+               willCS = willCauseSpill (sym);
+               spillable = computeSpillable (ic);
+               if (sym->remat || (willCS && bitVectIsZero (spillable))) {                    
+                   spillThis (sym);
+                   continue;                 
+               }
+
+               /* if it has a spillocation & is used less than
+                  all other live ranges then spill this */
+               if (willCS) {
+                   if (sym->usl.spillLoc) {
+                       symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
+                                                                        allLRs, ebbs[i], ic));
+                       if (leastUsed && leastUsed->used > sym->used) {
+                           spillThis (sym);
+                           continue;
+                       }
+                   } else {
+                       /* if none of the liveRanges have a spillLocation then better
+                          to spill this one than anything else already assigned to registers */
+                       if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
+                           /* if this is local to this block then we might find a block spil */
+                           if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) {
+                               spillThis (sym);
+                               continue;
+                           }
+                       }
+                   }
+               }
+
+               /* else we assign registers to it */
+               _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
+               _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key);
+
+               if (sym->regType == REG_PTR)
+                 getRegPtr (ic, ebbs[i], sym, 0);
+               else
+                 getRegGpr (ic, ebbs[i], sym, 0);
+               
+               /* if it shares registers with operands make sure
+                  that they are in the same position */
+               if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
+                   OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=') {
+                   positionRegs (OP_SYMBOL (IC_RESULT (ic)),
+                                 OP_SYMBOL (IC_LEFT (ic)));
+               }
+               /* do the same for the right operand */
+               if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
+                   OP_SYMBOL (IC_RIGHT (ic))->nRegs) {
+                   positionRegs (OP_SYMBOL (IC_RESULT (ic)),
+                                 OP_SYMBOL (IC_RIGHT (ic)));
+               }
+           }
+       }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* rUmaskForOp :- returns register mask for an operand             */
+/*-----------------------------------------------------------------*/
+bitVect *xa51_rUmaskForOp (operand * op) {
+  bitVect *rumask;
+  symbol *sym;
+  int j;
+  
+  /* only temporaries are assigned registers */
+  if (!IS_ITEMP (op))
+    return NULL;
+  
+  sym = OP_SYMBOL (op);
+  
+  /* if spilt or no registers assigned to it 
+     then nothing */
+  if (sym->isspilt || !sym->nRegs || !sym->regs[0])
+    return NULL;
+  
+  rumask = newBitVect (xa51_nRegs);
+  
+  for (j = 0; j < sym->nRegs; j++) {
+    rumask = bitVectSetBit (rumask,
+                           sym->regs[j]->rIdx);
+  }
+  return rumask;
+}
+
+/*-----------------------------------------------------------------*/
+/* regsUsedIniCode :- returns bit vector of registers used in iCode */
+/*-----------------------------------------------------------------*/
+static bitVect *
+regsUsedIniCode (iCode * ic)
+{
+  bitVect *rmask = newBitVect (xa51_nRegs);
+
+  /* do the special cases first */
+  if (ic->op == IFX)
+    {
+      rmask = bitVectUnion (rmask,
+                           xa51_rUmaskForOp (IC_COND (ic)));
+      goto ret;
+    }
+
+  /* for the jumptable */
+  if (ic->op == JUMPTABLE)
+    {
+      rmask = bitVectUnion (rmask,
+                           xa51_rUmaskForOp (IC_JTCOND (ic)));
+
+      goto ret;
+    }
+
+  /* of all other cases */
+  if (IC_LEFT (ic))
+    rmask = bitVectUnion (rmask,
+                         xa51_rUmaskForOp (IC_LEFT (ic)));
+
+
+  if (IC_RIGHT (ic))
+    rmask = bitVectUnion (rmask,
+                         xa51_rUmaskForOp (IC_RIGHT (ic)));
+
+  if (IC_RESULT (ic))
+    rmask = bitVectUnion (rmask,
+                         xa51_rUmaskForOp (IC_RESULT (ic)));
+
+ret:
+  return rmask;
+}
+
+/*-----------------------------------------------------------------*/
+/* createRegMask - for each instruction will determine the regsUsed */
+/*-----------------------------------------------------------------*/
+static void
+createRegMask (eBBlock ** ebbs, int count)
+{
+  int i;
+
+  /* for all blocks */
+  for (i = 0; i < count; i++)
+    {
+      iCode *ic;
+
+      if (ebbs[i]->noPath &&
+         (ebbs[i]->entryLabel != entryLabel &&
+          ebbs[i]->entryLabel != returnLabel))
+       continue;
+
+      /* for all instructions */
+      for (ic = ebbs[i]->sch; ic; ic = ic->next)
+       {
+
+         int j;
+
+         if (SKIP_IC2 (ic) || !ic->rlive)
+           continue;
+
+         /* first mark the registers used in this
+            instruction */
+         ic->rUsed = regsUsedIniCode (ic);
+         _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
+
+         /* now create the register mask for those 
+            registers that are in use : this is a
+            super set of ic->rUsed */
+         ic->rMask = newBitVect (xa51_nRegs + 1);
+
+         /* for all live Ranges alive at this point */
+         for (j = 1; j < ic->rlive->size; j++)
+           {
+             symbol *sym;
+             int k;
+
+             /* if not alive then continue */
+             if (!bitVectBitValue (ic->rlive, j))
+               continue;
+
+             /* find the live range we are interested in */
+             if (!(sym = hTabItemWithKey (liveRanges, j)))
+               {
+                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                         "createRegMask cannot find live range");
+                 exit (0);
+               }
+
+             /* if no register assigned to it */
+             if (!sym->nRegs || sym->isspilt)
+               continue;
+
+             /* for all the registers allocated to it */
+             for (k = 0; k < sym->nRegs; k++)
+               if (sym->regs[k])
+                 ic->rMask =
+                   bitVectSetBit (ic->rMask, sym->regs[k]->rIdx);
+           }
+       }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* rematStr - returns the rematerialized string for a remat var    */
+/*-----------------------------------------------------------------*/
+static char *
+rematStr (symbol * sym)
+{
+  char *s = buffer;
+  iCode *ic = sym->rematiCode;
+
+  while (1)
+    {
+
+      /* if plus or minus print the right hand side */
+      if (ic->op == '+' || ic->op == '-')
+       {
+         sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
+                  ic->op);
+         s += strlen (s);
+         ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+         continue;
+       }
+
+      /* cast then continue */
+      if (IS_CAST_ICODE(ic)) {
+         ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
+         continue;
+      }
+      /* we reached the end */
+      sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
+      break;
+    }
+
+  return buffer;
+}
+
+/*-----------------------------------------------------------------*/
+/* regTypeNum - computes the type & number of registers required   */
+/*-----------------------------------------------------------------*/
+static void
+regTypeNum (eBBlock *ebbs)
+{
+  symbol *sym;
+  int k;
+  iCode *ic;
+
+  /* for each live range do */
+  for (sym = hTabFirstItem (liveRanges, &k); sym;
+       sym = hTabNextItem (liveRanges, &k))
+    {
+
+      /* if used zero times then no registers needed */
+      if ((sym->liveTo - sym->liveFrom) == 0)
+       continue;
+
+
+      /* if the live range is a temporary */
+      if (sym->isitmp)
+       {
+
+         /* if the type is marked as a conditional */
+         if (sym->regType == REG_CND)
+           continue;
+
+         /* if used in return only then we don't 
+            need registers */
+#if 0 // not yet
+         if (sym->ruonly || sym->accuse)
+           {
+             if (IS_AGGREGATE (sym->type) || sym->isptr)
+               sym->type = aggrToPtr (sym->type, FALSE);
+             continue;
+           }
+#endif
+
+         /* if the symbol has only one definition &
+            that definition is a get_pointer and the
+            pointer we are getting is rematerializable and
+            in "data" space */
+
+         if (bitVectnBitsOn (sym->defs) == 1 &&
+             (ic = hTabItemWithKey (iCodehTab,
+                                    bitVectFirstBit (sym->defs))) &&
+             POINTER_GET (ic) &&
+             !sym->noSpilLoc &&
+             !IS_BITVAR (sym->etype))
+           {
+
+
+             /* if remat in data space */
+             if (OP_SYMBOL (IC_LEFT (ic))->remat &&
+                 !IS_CAST_ICODE(OP_SYMBOL (IC_LEFT (ic))->rematiCode) &&
+                 DCL_TYPE (aggrToPtr (sym->type, FALSE)) == POINTER)
+               {
+                 /* create a psuedo symbol & force a spil */
+                 symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
+                 psym->type = sym->type;
+                 psym->etype = sym->etype;
+                 strcpy (psym->rname, psym->name);
+                 sym->isspilt = 1;
+                 sym->usl.spillLoc = psym;
+#if 0 // an alternative fix for bug #480076
+                 /* now this is a useless assignment to itself */
+                 remiCodeFromeBBlock (ebbs, ic);
+#else
+                 /* now this really is an assignment to itself, make it so;
+                    it will be optimized out later */
+                 ic->op='=';
+                 IC_RIGHT(ic)=IC_RESULT(ic);
+                 IC_LEFT(ic)=NULL;
+#endif
+                 continue;
+               }
+
+             /* if in data space or idata space then try to
+                allocate pointer register */
+
+           }
+
+         /* if not then we require registers */
+#if 0
+         sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
+                       getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
+                       getSize (sym->type));
+#else
+         {
+           int size=((IS_AGGREGATE (sym->type) || sym->isptr) ?
+                     getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
+                     getSize (sym->type));
+           switch (size) 
+             {
+             case 1: // byte
+             case 2: // word or pointer
+               sym->nRegs=1;
+               break;
+             case 3: // generic pointer
+               sym->nRegs=2;
+               break;
+             case 4: // dword or float
+               sym->nRegs=2;
+               break;
+             default: 
+               fprintf (stderr, "regTypeNum: unknown size\n");
+               exit (1);
+             }
+         }
+#endif
+
+         if (sym->nRegs > 4)
+           {
+             fprintf (stderr, "allocated more than 4 or 0 registers for type ");
+             printTypeChain (sym->type, stderr);
+             fprintf (stderr, "\n");
+           }
+
+         /* determine the type of register required */
+         if (IS_PTR (sym->type))
+           sym->regType = REG_PTR;
+         else
+           sym->regType = REG_GPR;
+
+       }
+      else
+       /* for the first run we don't provide */
+       /* registers for true symbols we will */
+       /* see how things go                  */
+       sym->nRegs = 0;
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* deallocStackSpil - this will set the stack pointer back         */
+/*-----------------------------------------------------------------*/
+static
+DEFSETFUNC (deallocStackSpil)
+{
+  symbol *sym = item;
+
+  deallocLocal (sym);
+  return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* packRegsForAssign - register reduction for assignment           */
+/*-----------------------------------------------------------------*/
+static int
+packRegsForAssign (iCode * ic, eBBlock * ebp)
+{
+  iCode *dic, *sic;
+
+  if (!IS_ITEMP (IC_RIGHT (ic)) ||
+      OP_LIVETO (IC_RIGHT (ic)) > ic->seq) {
+    return 0;
+  }
+
+  /* find the definition of iTempNN scanning backwards */
+  for (dic = ic->prev; dic; dic = dic->prev) {
+
+    /* if there is a function call then don't pack it */
+    if ((dic->op == CALL || dic->op == PCALL)) {
+      dic = NULL;
+      break;
+    }
+    
+    if (SKIP_IC2 (dic))
+      continue;
+
+    if (IS_SYMOP (IC_RESULT (dic)) &&
+       IC_RESULT (dic)->key == IC_RIGHT (ic)->key) {
+      break;
+    }
+
+  }
+
+  if (!dic)
+    return 0;                  /* did not find */
+
+  /* found the definition */
+  /* replace the result with the result of */
+  /* this assignment and remove this assignment */
+  bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+  IC_RESULT (dic) = IC_RESULT (ic);
+
+  if (IS_ITEMP (IC_RESULT (dic)) && 
+      OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
+    {
+      OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
+    }
+  /* delete from liverange table also 
+     delete from all the points inbetween and the new
+     one */
+  for (sic = dic; sic != ic; sic = sic->next)
+    {
+      bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
+      if (IS_ITEMP (IC_RESULT (dic)))
+       bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
+    }
+
+  remiCodeFromeBBlock (ebp, ic);
+  bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+  hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+  OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+  return 1;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* findAssignToSym : scanning backwards looks for first assig found */
+/*-----------------------------------------------------------------*/
+static iCode *
+findAssignToSym (operand * op, iCode * ic)
+{
+  iCode *dic;
+
+  for (dic = ic->prev; dic; dic = dic->prev)
+    {
+
+      /* if definition by assignment */
+      if (dic->op == '=' &&
+         !POINTER_SET (dic) &&
+         IC_RESULT (dic)->key == op->key
+/*          &&  IS_TRUE_SYMOP(IC_RIGHT(dic)) */
+       )
+       {
+
+         /* we are interested only if defined in far space */
+         /* or in stack space in case of + & - */
+
+         /* if assigned to a non-symbol then return
+            FALSE */
+         if (!IS_SYMOP (IC_RIGHT (dic)))
+           return NULL;
+
+         /* if the symbol is in far space then
+            we should not */
+         if (isOperandInFarSpace (IC_RIGHT (dic)))
+           return NULL;
+
+         /* for + & - operations make sure that
+            if it is on the stack it is the same
+            as one of the three operands */
+         if ((ic->op == '+' || ic->op == '-') &&
+             OP_SYMBOL (IC_RIGHT (dic))->onStack)
+           {
+
+             if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
+                 IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
+                 IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
+               return NULL;
+           }
+
+         break;
+
+       }
+
+      /* if we find an usage then we cannot delete it */
+      if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
+       return NULL;
+
+      if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
+       return NULL;
+
+      if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
+       return NULL;
+    }
+
+  /* now make sure that the right side of dic
+     is not defined between ic & dic */
+  if (dic)
+    {
+      iCode *sic = dic->next;
+
+      for (; sic != ic; sic = sic->next)
+       if (IC_RESULT (sic) &&
+           IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
+         return NULL;
+    }
+
+  return dic;
+
+
+}
+
+/*-----------------------------------------------------------------*/
+/* packRegsForSupport :- reduce some registers for support calls   */
+/*-----------------------------------------------------------------*/
+static int
+packRegsForSupport (iCode * ic, eBBlock * ebp)
+{
+  int change = 0;
+  iCode *dic, *sic;
+
+  /* for the left & right operand :- look to see if the
+     left was assigned a true symbol in far space in that
+     case replace them */
+
+  if (IS_ITEMP (IC_LEFT (ic)) &&
+      OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
+    {
+      dic = findAssignToSym (IC_LEFT (ic), ic);
+
+      if (!dic)
+       goto right;
+
+      /* found it we need to remove it from the
+         block */
+      for (sic = dic; sic != ic; sic = sic->next)
+       bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
+
+      OP_SYMBOL(IC_LEFT (ic))=OP_SYMBOL(IC_RIGHT (dic));
+      IC_LEFT (ic)->key = OP_SYMBOL(IC_RIGHT (dic))->key;
+      remiCodeFromeBBlock (ebp, dic);
+      bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+      hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+      change++;
+    }
+
+  /* do the same for the right operand */
+ right:
+  if (!change &&
+      IS_ITEMP (IC_RIGHT (ic)) &&
+      OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
+    {
+      iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
+      iCode *sic;
+
+      if (!dic)
+       return change;
+
+      /* if this is a subtraction & the result
+         is a true symbol in far space then don't pack */
+      if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
+       {
+         sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
+         if (IN_FARSPACE (SPEC_OCLS (etype)))
+           return change;
+       }
+      /* found it we need to remove it from the
+         block */
+      for (sic = dic; sic != ic; sic = sic->next)
+       bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
+
+      IC_RIGHT (ic)->operand.symOperand =
+       IC_RIGHT (dic)->operand.symOperand;
+      IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
+
+      remiCodeFromeBBlock (ebp, dic);
+      bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+      hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+      change++;
+    }
+
+  return change;
+}
+
+#define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
+
+
+/*-----------------------------------------------------------------*/
+/* packRegsForOneuse : - will reduce some registers for single Use */
+/*-----------------------------------------------------------------*/
+static iCode *
+packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
+{
+  bitVect *uses;
+  iCode *dic, *sic;
+
+  /* if returning a literal then do nothing */
+  if (!IS_SYMOP (op))
+    return NULL;
+
+  if (ic->op != RETURN &&
+      ic->op != SEND &&
+      !POINTER_SET (ic) &&
+      !POINTER_GET (ic))
+    return NULL;
+  
+  /* this routine will mark the a symbol as used in one 
+     instruction use only && if the defintion is local 
+     (ie. within the basic block) && has only one definition &&
+     that definiion is either a return value from a 
+     function or does not contain any variables in
+     far space */
+  uses = bitVectCopy (OP_USES (op));
+  bitVectUnSetBit (uses, ic->key);     /* take away this iCode */
+  if (!bitVectIsZero (uses))   /* has other uses */
+    return NULL;
+
+  /* if it has only one defintion */
+  if (bitVectnBitsOn (OP_DEFS (op)) > 1)
+    return NULL;               /* has more than one definition */
+
+  /* get that definition */
+  if (!(dic =
+       hTabItemWithKey (iCodehTab,
+                        bitVectFirstBit (OP_DEFS (op)))))
+    return NULL;
+
+  /* if that only usage is a cast */
+  if (dic->op == CAST) {
+    /* to a bigger type */
+    if (getSize(OP_SYM_TYPE(IC_RESULT(dic))) > 
+       getSize(OP_SYM_TYPE(IC_RIGHT(dic)))) {
+      /* than we can not, since we cannot predict the usage of b & acc */
+      return NULL;
+    }
+  }
+
+  /* found the definition now check if it is local */
+  if (dic->seq < ebp->fSeq ||
+      dic->seq > ebp->lSeq)
+    return NULL;               /* non-local */
+
+  /* now check if it is the return from
+     a function call */
+  if (dic->op == CALL || dic->op == PCALL)
+    {
+      if (ic->op != SEND && ic->op != RETURN &&
+         !POINTER_SET(ic) && !POINTER_GET(ic))
+       {
+         OP_SYMBOL (op)->ruonly = 1;
+         return dic;
+       }
+      dic = dic->next;
+    }
+
+
+  /* otherwise check that the definition does
+     not contain any symbols in far space */
+  if (isOperandInFarSpace (IC_LEFT (dic)) ||
+      isOperandInFarSpace (IC_RIGHT (dic)) ||
+      IS_OP_RUONLY (IC_LEFT (ic)) ||
+      IS_OP_RUONLY (IC_RIGHT (ic)))
+    {
+      return NULL;
+    }
+
+  /* if pointer set then make sure the pointer
+     is one byte */
+  if (POINTER_SET (dic) &&
+      !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
+    return NULL;
+
+  if (POINTER_GET (dic) &&
+      !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
+    return NULL;
+
+  sic = dic;
+
+  /* also make sure the intervenening instructions
+     don't have any thing in far space */
+  for (dic = dic->next; dic && dic != ic && sic != ic; dic = dic->next)
+    {
+
+      /* if there is an intervening function call then no */
+      if (dic->op == CALL || dic->op == PCALL)
+       return NULL;
+      /* if pointer set then make sure the pointer
+         is one byte */
+      if (POINTER_SET (dic) &&
+         !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
+       return NULL;
+
+      if (POINTER_GET (dic) &&
+         !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
+       return NULL;
+
+      /* if address of & the result is remat the okay */
+      if (dic->op == ADDRESS_OF &&
+         OP_SYMBOL (IC_RESULT (dic))->remat)
+       continue;
+
+      /* if operand has size of three or more & this
+         operation is a '*','/' or '%' then 'b' may
+         cause a problem */
+      if ((dic->op == '%' || dic->op == '/' || dic->op == '*') &&
+         getSize (operandType (op)) >= 3)
+       return NULL;
+
+      /* if left or right or result is in far space */
+      if (isOperandInFarSpace (IC_LEFT (dic)) ||
+         isOperandInFarSpace (IC_RIGHT (dic)) ||
+         isOperandInFarSpace (IC_RESULT (dic)) ||
+         IS_OP_RUONLY (IC_LEFT (dic)) ||
+         IS_OP_RUONLY (IC_RIGHT (dic)) ||
+         IS_OP_RUONLY (IC_RESULT (dic)))
+       {
+         return NULL;
+       }
+      /* if left or right or result is on stack */
+      if (isOperandOnStack(IC_LEFT(dic)) ||
+         isOperandOnStack(IC_RIGHT(dic)) ||
+         isOperandOnStack(IC_RESULT(dic))) {
+       return NULL;
+      }
+    }
+
+  OP_SYMBOL (op)->ruonly = 1;
+  return sic;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* isBitwiseOptimizable - requirements of JEAN LOUIS VERN          */
+/*-----------------------------------------------------------------*/
+static bool
+isBitwiseOptimizable (iCode * ic)
+{
+  sym_link *ltype = getSpec (operandType (IC_LEFT (ic)));
+  sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
+
+  /* bitwise operations are considered optimizable
+     under the following conditions (Jean-Louis VERN) 
+
+     x & lit
+     bit & bit
+     bit & x
+     bit ^ bit
+     bit ^ x
+     x   ^ lit
+     x   | lit
+     bit | bit
+     bit | x
+  */
+  if (IS_LITERAL(rtype) ||
+      (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* packForPush - hueristics to reduce iCode for pushing            */
+/*-----------------------------------------------------------------*/
+static void
+packForPush (iCode * ic, eBBlock * ebp)
+{
+  iCode *dic, *lic;
+  bitVect *dbv;
+
+  if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
+    return;
+
+  /* must have only definition & one usage */
+  if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 ||
+      bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1)
+    return;
+
+  /* find the definition */
+  if (!(dic = hTabItemWithKey (iCodehTab,
+                              bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
+    return;
+
+  if (dic->op != '=' || POINTER_SET (dic))
+    return;
+
+  /* make sure the right side does not have any definitions
+     inbetween */
+  dbv = OP_DEFS(IC_RIGHT(dic));
+  for (lic = ic; lic && lic != dic ; lic = lic->prev) {
+    if (bitVectBitValue(dbv,lic->key)) 
+      return ;
+  }
+  /* make sure they have the same type */
+  {
+    sym_link *itype=operandType(IC_LEFT(ic));
+    sym_link *ditype=operandType(IC_RIGHT(dic));
+
+    if (SPEC_USIGN(itype)!=SPEC_USIGN(ditype) ||
+       SPEC_LONG(itype)!=SPEC_LONG(ditype))
+      return;
+  }
+  /* extend the live range of replaced operand if needed */
+  if (OP_SYMBOL(IC_RIGHT(dic))->liveTo < ic->seq) {
+         OP_SYMBOL(IC_RIGHT(dic))->liveTo = ic->seq;
+  }
+  /* we now know that it has one & only one def & use
+     and the that the definition is an assignment */
+  IC_LEFT (ic) = IC_RIGHT (dic);
+   
+  remiCodeFromeBBlock (ebp, dic);
+  bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+  hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+}
+
+/*-----------------------------------------------------------------*/
+/* packRegisters - does some transformations to reduce register    */
+/*                   pressure                                      */
+/*-----------------------------------------------------------------*/
+static void packRegisters (eBBlock * ebp) {
+  iCode *ic;
+  int change = 0;
+  
+  while (1) {
+    change = 0;
+    
+    for (ic = ebp->sch; ic; ic = ic->next) {
+      if (ic->op == '=')
+       change += packRegsForAssign (ic, ebp);
+    }
+    
+    if (!change)
+      break;
+  }
+  return; // that's it for now
+
+  for (ic = ebp->sch; ic; ic = ic->next)
+    {
+      /* if this is an itemp & result of an address of a true sym 
+         then mark this as rematerialisable   */
+      if (ic->op == ADDRESS_OF &&
+         IS_ITEMP (IC_RESULT (ic)) &&
+         IS_TRUE_SYMOP (IC_LEFT (ic)) &&
+         bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
+         !OP_SYMBOL (IC_LEFT (ic))->onStack)
+       {
+
+         OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+         OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+         OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+
+       }
+
+      /* if straight assignment then carry remat flag if
+         this is the only definition */
+      if (ic->op == '=' &&
+         !POINTER_SET (ic) &&
+         IS_SYMOP (IC_RIGHT (ic)) &&
+         OP_SYMBOL (IC_RIGHT (ic))->remat &&
+         !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode) &&
+         bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
+       {
+
+         OP_SYMBOL (IC_RESULT (ic))->remat =
+           OP_SYMBOL (IC_RIGHT (ic))->remat;
+         OP_SYMBOL (IC_RESULT (ic))->rematiCode =
+           OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
+       }
+
+      /* if cast to a generic pointer & the pointer being
+        cast is remat, then we can remat this cast as well */
+      if (ic->op == CAST && 
+         IS_SYMOP(IC_RIGHT(ic)) &&
+         OP_SYMBOL(IC_RIGHT(ic))->remat ) {
+             sym_link *to_type = operandType(IC_LEFT(ic));
+             sym_link *from_type = operandType(IC_RIGHT(ic));
+             if (IS_GENPTR(to_type) && IS_PTR(from_type)) {                  
+                     OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+                     OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+                     OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+             }
+      }
+
+      /* if this is a +/- operation with a rematerizable 
+         then mark this as rematerializable as well */
+      if ((ic->op == '+' || ic->op == '-') &&
+         (IS_SYMOP (IC_LEFT (ic)) &&
+          IS_ITEMP (IC_RESULT (ic)) &&
+          IS_OP_LITERAL (IC_RIGHT (ic))) &&
+          OP_SYMBOL (IC_LEFT (ic))->remat &&
+         (!IS_SYMOP (IC_RIGHT (ic)) || !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode)) &&
+          bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1)
+       {
+         OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+         OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+         OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+       }
+
+      /* mark the pointer usages */
+      if (POINTER_SET (ic))
+       OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
+
+      if (POINTER_GET (ic))
+       OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
+
+      /* if the condition of an if instruction
+         is defined in the previous instruction and
+        this is the only usage then
+         mark the itemp as a conditional */
+      if ((IS_CONDITIONAL (ic) ||
+          (IS_BITWISE_OP(ic) && isBitwiseOptimizable (ic))) &&
+         ic->next && ic->next->op == IFX &&
+         bitVectnBitsOn (OP_USES(IC_RESULT(ic)))==1 &&
+         isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
+         OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
+       {
+         OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
+         continue;
+       }
+
+      /* reduce for support function calls */
+      if (ic->supportRtn || ic->op == '+' || ic->op == '-')
+       packRegsForSupport (ic, ebp);
+
+      /* some cases the redundant moves can
+         can be eliminated for return statements */
+      if ((ic->op == RETURN || ic->op == SEND) &&
+         !isOperandInFarSpace (IC_LEFT (ic)) &&
+         options.model == MODEL_SMALL) {
+       if (0 && options.stackAuto) {
+         /* we should check here if acc will be clobbered for stack
+            offset calculations */
+       } else {
+         packRegsForOneuse (ic, IC_LEFT (ic), ebp);
+       }
+      }
+
+      /* if pointer set & left has a size more than
+         one and right is not in far space */
+      if (POINTER_SET (ic) &&
+         !isOperandInFarSpace (IC_RIGHT (ic)) &&
+         !OP_SYMBOL (IC_RESULT (ic))->remat &&
+         !IS_OP_RUONLY (IC_RIGHT (ic)) &&
+         getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
+
+       packRegsForOneuse (ic, IC_RESULT (ic), ebp);
+
+      /* if pointer get */
+      if (POINTER_GET (ic) &&
+         !isOperandInFarSpace (IC_RESULT (ic)) &&
+         !OP_SYMBOL (IC_LEFT (ic))->remat &&
+         !IS_OP_RUONLY (IC_RESULT (ic)) &&
+         getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1)
+
+       packRegsForOneuse (ic, IC_LEFT (ic), ebp);
+
+
+      /* if this is cast for intergral promotion then
+         check if only use of  the definition of the 
+         operand being casted/ if yes then replace
+         the result of that arithmetic operation with 
+         this result and get rid of the cast */
+      if (ic->op == CAST)
+       {
+         sym_link *fromType = operandType (IC_RIGHT (ic));
+         sym_link *toType = operandType (IC_LEFT (ic));
+
+         if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
+             getSize (fromType) != getSize (toType) &&
+             SPEC_USIGN (fromType) == SPEC_USIGN (toType))
+           {
+
+             iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
+             if (dic)
+               {
+                 if (IS_ARITHMETIC_OP (dic))
+                   {                  
+                     bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+                     IC_RESULT (dic) = IC_RESULT (ic);
+                     remiCodeFromeBBlock (ebp, ic);
+                     bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+                     hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+                     OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+                     ic = ic->prev;
+                   }
+                 else
+                   OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
+               }
+           }
+         else
+           {
+
+             /* if the type from and type to are the same
+                then if this is the only use then packit */
+             if (compareType (operandType (IC_RIGHT (ic)),
+                            operandType (IC_LEFT (ic))) == 1)
+               {
+                 iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
+                 if (dic)
+                   {
+                     bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+                     IC_RESULT (dic) = IC_RESULT (ic);
+                     remiCodeFromeBBlock (ebp, ic);
+                     bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+                     hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+                     OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+                     ic = ic->prev;
+                   }
+               }
+           }
+       }
+
+      /* pack for PUSH 
+         iTempNN := (some variable in farspace) V1
+         push iTempNN ;
+         -------------
+         push V1
+       */
+      if (ic->op == IPUSH)
+       {
+         packForPush (ic, ebp);
+       }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* assignRegisters - assigns registers to each live range as need  */
+/*-----------------------------------------------------------------*/
+void
+xa51_assignRegisters (eBBlock ** ebbs, int count)
+{
+  iCode *ic;
+  int i;
+
+  setToNull ((void *) &_G.funcrUsed);
+  setToNull ((void *) &_G.totRegAssigned);
+  _G.stackExtend = _G.dataExtend = 0;
+
+  /* change assignments this will remove some
+     live ranges reducing some register pressure */
+  for (i = 0; i < count; i++)
+    packRegisters (ebbs[i]);
+
+  if (options.dump_pack)
+    dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
+
+  /* first determine for each live range the number of 
+     registers & the type of registers required for each */
+  regTypeNum (*ebbs);
+
+  /* and serially allocate registers */
+  serialRegAssign (ebbs, count);
+
+  freeAllRegs ();
+
+  /* if stack was extended then tell the user */
+  if (_G.stackExtend)
+    {
+/*      werror(W_TOOMANY_SPILS,"stack", */
+/*             _G.stackExtend,currFunc->name,""); */
+      _G.stackExtend = 0;
+    }
+
+  if (_G.dataExtend)
+    {
+/*      werror(W_TOOMANY_SPILS,"data space", */
+/*             _G.dataExtend,currFunc->name,""); */
+      _G.dataExtend = 0;
+    }
+
+  /* after that create the register mask
+     for each of the instruction */
+  createRegMask (ebbs, count);
+
+  /* redo that offsets for stacked automatic variables */
+  redoStackOffsets ();
+
+  if (options.dump_rassgn)
+    {
+      dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
+      dumpLiveRanges (DUMP_LRANGE, liveRanges);
+    }
+
+  /* do the overlaysegment stuff SDCCmem.c */
+  doOverlays (ebbs, count);
+
+  /* now get back the chain */
+  ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
+
+  genXA51Code (ic);
+
+  /* free up any _G.stackSpil locations allocated */
+  applyToSet (_G.stackSpil, deallocStackSpil);
+  _G.slocNum = 0;
+  setToNull ((void **) &_G.stackSpil);
+  setToNull ((void **) &_G.spiltSet);
+  /* mark all registers as free */
+  freeAllRegs ();
+
+  return;
+}
diff --git a/src/xa51/ralloc.h b/src/xa51/ralloc.h
new file mode 100755 (executable)
index 0000000..bddd52b
--- /dev/null
@@ -0,0 +1,81 @@
+/*-------------------------------------------------------------------------
+
+  SDCCralloc.h - header file register allocation
+
+                Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!  
+-------------------------------------------------------------------------*/
+#include "SDCCicode.h"
+#include "SDCCBBlock.h"
+#ifndef SDCCRALLOC_H
+#define SDCCRALLOC_H 1
+
+#define ubyte unsigned char
+#define byte ubyte
+#define sbyte signed char
+#define uword unsigned char
+#define word uword
+#define sword signed char
+#define udword unsigned int
+#define dword udword
+#define sdword signed int
+
+#define REG_PTR 0x01 // pointer register
+#define REG_GPR 0x02 // general purpose register
+#define REG_CND 0x04 // condition (bit) register
+#define REG_SCR 0x40 // scratch register
+#define REG_STK 0x80 // stack pointer register
+
+typedef struct regs {
+  ubyte rIdx; // a unique # for this one
+  ubyte size; // size of register (0,1,2,4)
+  ubyte type; // pointer, general purpose, condition (bit)
+  char *name;
+  udword regMask;
+  uword offset;
+  bool isFree;
+  symbol *sym;
+} regs;
+
+#if 0
+/* definition for the registers */
+typedef struct regs
+  {
+    short type;                        /* can have value REG_CND, REG_8BITS, 
+                                  REG_16BITS or REG_32BITS */
+    short rIdx;                        /* index into register table */
+    short otype;
+    char *name;                        /* name */
+    char *dname;               /* name when direct access needed */
+    char *base;                        /* base address */
+    short offset;              /* offset from the base */
+    unsigned isFree:1;         /* is currently unassigned  */
+  }
+regs;
+#endif
+
+extern regs regsXA51[];
+extern udword xa51RegsInUse;
+
+regs *xa51_regWithIdx (int);
+
+bitVect *xa51_rUmaskForOp (operand * op);
+
+#endif
diff --git a/src/xa51/ralloc.o b/src/xa51/ralloc.o
new file mode 100644 (file)
index 0000000..6e686e8
Binary files /dev/null and b/src/xa51/ralloc.o differ