diff --git a/gcc/config/rs6000/rs6000-genbif.c b/gcc/config/rs6000/rs6000-genbif.c
index 38401224dce..e7ce777afbb 100644
--- a/gcc/config/rs6000/rs6000-genbif.c
+++ b/gcc/config/rs6000/rs6000-genbif.c
@@ -156,7 +156,23 @@ enum void_status {
   VOID_OK
 };
 
+/* Stanzas are groupings of built-in functions and overloads by some
+   common feature/attribute.  These definitions are for built-in function
+   stanzas.  */
+#define MAXBIFSTANZAS 256
+static char *bif_stanzas[MAXBIFSTANZAS];
 static int num_bif_stanzas;
+static int curr_bif_stanza;
+
+/* Function modifiers provide special handling for const, pure, and math
+   functions.  These are mutually exclusive, and therefore kept separate
+   from other bif attributes.  */
+enum fnkinds {
+  FNK_NONE,
+  FNK_CONST,
+  FNK_PURE,
+  FNK_MATH
+};
 
 /* Legal base types for an argument or return type.  */
 enum basetype {
@@ -199,7 +215,54 @@ struct typeinfo {
   int val2;
 };
 
+/* A list of argument types.  */
+struct typelist {
+  typeinfo info;
+  typelist *next;
+};
+
+/* Attributes of a builtin function.  */
+struct attrinfo {
+  char isinit;
+  char isset;
+  char isext;
+  char isnosoft;
+  char isldv;
+  char isstv;
+  char isreve;
+  char isabs;
+  char ispred;
+  char ishtm;
+};
+
+/* Fields associated with a function prototype (bif or overload).  */
+struct prototype {
+  typeinfo rettype;
+  char *bifname;
+  int nargs;
+  typelist *args;
+  int restr_opnd;
+  restriction restr;
+  int restr_val1;
+  int restr_val2;
+};
+
+/* Data associated with a builtin function, and a table of such data.  */
+#define MAXBIFS 16384
+struct bifdata {
+  int stanza;
+  fnkinds kind;
+  prototype proto;
+  char *idname;
+  char *patname;
+  attrinfo attrs;
+  char *fndecl;
+};
+
+static bifdata bifs[MAXBIFS];
 static int num_bifs;
+static int curr_bif;
+
 static int num_ovld_stanzas;
 static int num_ovlds;
 
@@ -747,11 +810,419 @@ match_type (typeinfo *typedata, int voidok)
   return match_basetype (typedata);
 }
 
+/* Parse the argument list, returning 1 if success or 0 if any
+   malformation is found.  */
+static int
+parse_bif_args (prototype *protoptr)
+{
+  typelist **argptr = &protoptr->args;
+  int *nargs = &protoptr->nargs;
+  int *restr_opnd = &protoptr->restr_opnd;
+  restriction *restr = &protoptr->restr;
+  int *val1 = &protoptr->restr_val1;
+  int *val2 = &protoptr->restr_val2;
+
+  int success;
+  *nargs = 0;
+
+  /* Start the argument list.  */
+  consume_whitespace ();
+  if (linebuf[pos] != '(')
+    {
+      (*diag) ("missing '(' at column %d.\n", pos + 1);
+      return 0;
+    }
+  safe_inc_pos ();
+
+  do {
+    consume_whitespace ();
+    int oldpos = pos;
+    typelist *argentry = (typelist *) malloc (sizeof (typelist));
+    memset (argentry, 0, sizeof (*argentry));
+    typeinfo *argtype = &argentry->info;
+    success = match_type (argtype, VOID_NOTOK);
+    if (success)
+      {
+	if (argtype->restr)
+	  {
+	    if (*restr_opnd)
+	      {
+		(*diag) ("More than one restricted operand\n");
+		return 0;
+	      }
+	    *restr_opnd = *nargs;
+	    *restr = argtype->restr;
+	    *val1 = argtype->val1;
+	    *val2 = argtype->val2;
+	  }
+	(*nargs)++;
+	*argptr = argentry;
+	argptr = &argentry->next;
+	consume_whitespace ();
+	if (linebuf[pos] == ',')
+	  safe_inc_pos ();
+	else if (linebuf[pos] != ')')
+	  {
+	    (*diag) ("arg not followed by ',' or ')' at column %d.\n",
+		     pos + 1);
+	    return 0;
+	  }
+
+#ifdef DEBUG
+	(*diag) ("argument type: isvoid = %d, isconst = %d, isvector = %d, \
+issigned = %d, isunsigned = %d, isbool = %d, ispixel = %d, ispointer = %d, \
+base = %d, restr = %d, val1 = %d, val2 = %d, pos = %d.\n",
+		 argtype->isvoid, argtype->isconst, argtype->isvector,
+		 argtype->issigned, argtype->isunsigned, argtype->isbool,
+		 argtype->ispixel, argtype->ispointer, argtype->base,
+		 argtype->restr, argtype->val1, argtype->val2, pos + 1);
+#endif
+      }
+    else
+      {
+	free (argentry);
+	*argptr = NULL;
+	pos = oldpos;
+	if (linebuf[pos] != ')')
+	  {
+	    (*diag) ("badly terminated arg list at column %d.\n", pos + 1);
+	    return 0;
+	  }
+	safe_inc_pos ();
+      }
+  } while (success);
+
+  return 1;
+}
+
+/* Parse the attribute list, returning 1 if success or 0 if any
+   malformation is found.  */
+static int
+parse_bif_attrs (attrinfo *attrptr)
+{
+  consume_whitespace ();
+  if (linebuf[pos] != '{')
+    {
+      (*diag) ("missing attribute set at column %d.\n", pos + 1);
+      return 0;
+    }
+  safe_inc_pos ();
+
+  memset (attrptr, 0, sizeof (*attrptr));
+  char *attrname = NULL;
+
+  do {
+    consume_whitespace ();
+    int oldpos = pos;
+    attrname = match_identifier ();
+    if (attrname)
+      {
+	if (!strcmp (attrname, "init"))
+	  attrptr->isinit = 1;
+	else if (!strcmp (attrname, "set"))
+	  attrptr->isset = 1;
+	else if (!strcmp (attrname, "ext"))
+	  attrptr->isext = 1;
+	else if (!strcmp (attrname, "nosoft"))
+	  attrptr->isnosoft = 1;
+	else if (!strcmp (attrname, "ldv"))
+	  attrptr->isldv = 1;
+	else if (!strcmp (attrname, "stv"))
+	  attrptr->isstv = 1;
+	else if (!strcmp (attrname, "reve"))
+	  attrptr->isreve = 1;
+	else if (!strcmp (attrname, "abs"))
+	  attrptr->isabs = 1;
+	else if (!strcmp (attrname, "pred"))
+	  attrptr->ispred = 1;
+	else if (!strcmp (attrname, "htm"))
+	  attrptr->ishtm = 1;
+	else
+	  {
+	    (*diag) ("unknown attribute at column %d.\n", oldpos + 1);
+	    return 0;
+	  }
+
+	consume_whitespace ();
+	if (linebuf[pos] == ',')
+	  safe_inc_pos ();
+	else if (linebuf[pos] != '}')
+	  {
+	    (*diag) ("arg not followed by ',' or '}' at column %d.\n",
+		     pos + 1);
+	    return 0;
+	  }
+      }
+    else
+      {
+	pos = oldpos;
+	if (linebuf[pos] != '}')
+	  {
+	    (*diag) ("badly terminated attr set at column %d.\n", pos + 1);
+	    return 0;
+	  }
+	safe_inc_pos ();
+      }
+  } while (attrname);
+
+#ifdef DEBUG
+  (*diag) ("attribute set: init = %d, set = %d, ext = %d, \
+nosoft = %d, ldv = %d, stv = %d, reve = %d, abs = %d, pred = %d, \
+htm = %d.\n",
+	   attrptr->isinit, attrptr->isset, attrptr->isext, attrptr->isnosoft,
+	   attrptr->isldv, attrptr->isstv, attrptr->isreve, attrptr->isabs,
+	   attrptr->ispred, attrptr->ishtm);
+#endif
+
+  return 1;
+}
+
+/* Parse a function prototype.  This code is shared by the bif and overload
+   file processing.  Return 1 for success, 0 for failure.  */
+static int
+parse_prototype (prototype *protoptr)
+{
+  typeinfo *ret_type = &protoptr->rettype;
+  char **bifname = &protoptr->bifname;
+
+  /* Get the return type.  */
+  consume_whitespace ();
+  int oldpos = pos;
+  int success = match_type (ret_type, VOID_OK);
+  if (!success)
+    {
+      (*diag) ("missing or badly formed return type at column %d.\n",
+	       oldpos + 1);
+      return 0;
+    }
+
+#ifdef DEBUG
+  (*diag) ("return type: isvoid = %d, isconst = %d, isvector = %d, \
+issigned = %d, isunsigned = %d, isbool = %d, ispixel = %d, ispointer = %d, \
+base = %d, restr = %d, val1 = %d, val2 = %d, pos = %d.\n",
+	   ret_type->isvoid, ret_type->isconst, ret_type->isvector,
+	   ret_type->issigned, ret_type->isunsigned, ret_type->isbool,
+	   ret_type->ispixel, ret_type->ispointer, ret_type->base,
+	   ret_type->restr, ret_type->val1, ret_type->val2, pos + 1);
+#endif
+
+  /* Get the bif name.  */
+  consume_whitespace ();
+  oldpos = pos;
+  *bifname = match_identifier ();
+  if (!*bifname)
+    {
+      (*diag) ("missing function name at column %d.\n", oldpos + 1);
+      return 0;
+    }
+
+#ifdef DEBUG
+  (*diag) ("function name is '%s'.\n", *bifname);
+#endif
+
+  /* Process arguments.  */
+  if (!parse_bif_args (protoptr))
+    return 0;
+
+  /* Process terminating semicolon.  */
+  consume_whitespace ();
+  if (linebuf[pos] != ';')
+    {
+      (*diag) ("missing semicolon at column %d.\n", pos + 1);
+      return 0;
+    }
+  safe_inc_pos ();
+  consume_whitespace ();
+  if (linebuf[pos] != '\n')
+    {
+      (*diag) ("garbage at end of line at column %d.\n", pos + 1);
+      return 0;
+    }
+
+  return 1;
+}
+
+/* Parse a two-line entry for a built-in function.  Return 1 for
+   success, 2 for end-of-stanza, and 5 for a parsing error.  */
+static int
+parse_bif_entry ()
+{
+  /* Check for end of stanza.  */
+  pos = 0;
+  consume_whitespace ();
+  if (linebuf[pos] == '[')
+    return 2;
+
+  /* Allocate an entry in the bif table.  */
+  if (num_bifs >= MAXBIFS - 1)
+    {
+      (*diag) ("too many built-in functions.\n");
+      return 5;
+    }
+
+  curr_bif = num_bifs++;
+  bifs[curr_bif].stanza = curr_bif_stanza;
+
+  /* Read the first token and see if it is a function modifier.  */
+  consume_whitespace ();
+  int oldpos = pos;
+  char *token = match_identifier ();
+  if (!token)
+    {
+      (*diag) ("malformed entry at column %d\n", pos + 1);
+      return 5;
+    }
+
+  if (!strcmp (token, "const"))
+    bifs[curr_bif].kind = FNK_CONST;
+  else if (!strcmp (token, "pure"))
+    bifs[curr_bif].kind = FNK_PURE;
+  else if (!strcmp (token, "math"))
+    bifs[curr_bif].kind = FNK_MATH;
+  else
+    {
+      /* No function modifier, so push the token back.  */
+      pos = oldpos;
+      bifs[curr_bif].kind = FNK_NONE;
+    }
+
+  if (!parse_prototype (&bifs[curr_bif].proto))
+    return 5;
+
+  /* Now process line 2.  First up is the builtin id.  */
+  if (!advance_line (bif_file))
+    {
+      (*diag) ("unexpected EOF.\n");
+      return 5;
+    }
+
+  pos = 0;
+  consume_whitespace ();
+  oldpos = pos;
+  bifs[curr_bif].idname = match_identifier ();
+  if (!bifs[curr_bif].idname)
+    {
+      (*diag) ("missing builtin id at column %d.\n", pos + 1);
+      return 5;
+    }
+
+#ifdef DEBUG
+  (*diag) ("ID name is '%s'.\n", bifs[curr_bif].idname);
+#endif
+
+  /* Save the ID in a lookup structure.  */
+  if (!rbt_insert (&bif_rbt, bifs[curr_bif].idname))
+    {
+      (*diag) ("duplicate function ID '%s' at column %d.\n",
+	       bifs[curr_bif].idname, oldpos + 1);
+      return 5;
+    }
+
+  /* Now the pattern name.  */
+  consume_whitespace ();
+  bifs[curr_bif].patname = match_identifier ();
+  if (!bifs[curr_bif].patname)
+    {
+      (*diag) ("missing pattern name at column %d.\n", pos + 1);
+      return 5;
+    }
+
+#ifdef DEBUG
+  (*diag) ("pattern name is '%s'.\n", bifs[curr_bif].patname);
+#endif
+
+  /* Process attributes.  */
+  if (!parse_bif_attrs (&bifs[curr_bif].attrs))
+    return 5;
+
+  return 1;
+}
+
+/* Parse one stanza of the input BIF file.  linebuf already contains the
+   first line to parse.  Return 1 for success, 0 for EOF, 5 for failure.  */
+static int
+parse_bif_stanza ()
+{
+  /* Parse the stanza header.  */
+  pos = 0;
+  consume_whitespace ();
+
+  if (linebuf[pos] != '[')
+    {
+      (*diag) ("ill-formed stanza header at column %d.\n", pos + 1);
+      return 5;
+    }
+  safe_inc_pos ();
+
+  char *stanza_name = match_identifier ();
+  if (!stanza_name)
+    {
+      (*diag) ("no identifier found in stanza header.\n");
+      return 5;
+    }
+
+  /* Add the identifier to a table and set the number to be recorded
+     with subsequent bif entries.  */
+  if (num_bif_stanzas >= MAXBIFSTANZAS)
+    {
+      (*diag) ("too many stanza headers.\n");
+      return 5;
+    }
+
+  curr_bif_stanza = num_bif_stanzas;
+  bif_stanzas[num_bif_stanzas++] = stanza_name;
+
+  if (linebuf[pos] != ']')
+    {
+      (*diag) ("ill-formed stanza header at column %d.\n", pos + 1);
+      return 5;
+    }
+  safe_inc_pos ();
+
+  consume_whitespace ();
+  if (linebuf[pos] != '\n' && pos != LINELEN - 1)
+    {
+      (*diag) ("garbage after stanza header.\n");
+      return 5;
+    }
+
+  int result = 1;
+
+  while (result != 2) /* end of stanza  */
+    {
+      int result;
+      if (!advance_line (bif_file))
+	return 0;
+
+      result = parse_bif_entry();
+      if (!result) /* EOF */
+	return 0;
+      else if (result > 2)
+	return 5;
+    }
+
+  return 1;
+}
+
 /* Parse the built-in file.  Return 1 for success, 5 for a parsing failure.  */
 static int
 parse_bif ()
 {
-  return 1;
+  int result;
+  diag = &bif_diag;
+  while (1)
+    {
+      if (!advance_line (bif_file))
+	return 1;
+
+      /* Parse a stanza beginning at this line.  */
+      result = parse_bif_stanza ();
+      if (result != 1)
+	break;
+    }
+  if (result == 0)
+    return 1;
+  return result;
 }
 
 /* Parse the overload file.  Return 1 for success, 6 for a parsing error.  */
