case BFD_RELOC_16_GOTOFF: case BFD_RELOC_PPC_TOC16:
md_assemble (str)     char *str;{  char *s;  const struct powerpc_opcode *opcode;  unsigned long insn;  const unsigned char *opindex_ptr;  int skip_optional;  int need_paren;  int next_opindex;  struct ppc_fixup fixups[MAX_INSN_FIXUPS];  int fc;  char *f;  int i;#ifdef OBJ_ELF  bfd_reloc_code_real_type reloc;#endif  /* Get the opcode.  */  for (s = str; *s != '\0' && ! isspace (*s); s++)    ;  if (*s != '\0')    *s++ = '\0';  /* Look up the opcode in the hash table.  */  opcode = (const struct powerpc_opcode *) hash_find (ppc_hash, str);  if (opcode == (const struct powerpc_opcode *) NULL)    {      const struct powerpc_macro *macro;      macro = (const struct powerpc_macro *) hash_find (ppc_macro_hash, str);      if (macro == (const struct powerpc_macro *) NULL)	as_bad ("Unrecognized opcode: `%s'", str);      else	ppc_macro (s, macro);      return;    }  insn = opcode->opcode;  str = s;  while (isspace (*str))    ++str;  /* PowerPC operands are just expressions.  The only real issue is     that a few operand types are optional.  All cases which might use     an optional operand separate the operands only with commas (in     some cases parentheses are used, as in ``lwz 1,0(1)'' but such     cases never have optional operands).  There is never more than     one optional operand for an instruction.  So, before we start     seriously parsing the operands, we check to see if we have an     optional operand, and, if we do, we count the number of commas to     see whether the operand should be omitted.  */  skip_optional = 0;  for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)    {      const struct powerpc_operand *operand;      operand = &powerpc_operands[*opindex_ptr];      if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)	{	  unsigned int opcount;	  /* There is an optional operand.  Count the number of	     commas in the input line.  */	  if (*str == '\0')	    opcount = 0;	  else	    {	      opcount = 1;	      s = str;	      while ((s = strchr (s, ',')) != (char *) NULL)		{		  ++opcount;		  ++s;		}	    }	  /* If there are fewer operands in the line then are called	     for by the instruction, we want to skip the optional	     operand.  */	  if (opcount < strlen (opcode->operands))	    skip_optional = 1;	  break;	}    }  /* Gather the operands.  */  need_paren = 0;  next_opindex = 0;  fc = 0;  for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)    {      const struct powerpc_operand *operand;      const char *errmsg;      char *hold;      expressionS ex;      char endc;      if (next_opindex == 0)	operand = &powerpc_operands[*opindex_ptr];      else	{	  operand = &powerpc_operands[next_opindex];	  next_opindex = 0;	}      errmsg = NULL;      /* If this is a fake operand, then we do not expect anything	 from the input.  */      if ((operand->flags & PPC_OPERAND_FAKE) != 0)	{	  insn = (*operand->insert) (insn, 0L, &errmsg);	  if (errmsg != (const char *) NULL)	    as_warn (errmsg);	  continue;	}      /* If this is an optional operand, and we are skipping it, just	 insert a zero.  */      if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0	  && skip_optional)	{	  if (operand->insert)	    {	      insn = (*operand->insert) (insn, 0L, &errmsg);	      if (errmsg != (const char *) NULL)		as_warn (errmsg);	    }	  if ((operand->flags & PPC_OPERAND_NEXT) != 0)	    next_opindex = *opindex_ptr + 1;	  continue;	}      /* Gather the operand.  */      hold = input_line_pointer;      input_line_pointer = str;#ifdef TE_PE      if (*input_line_pointer == '[') 	{	  /* We are expecting something like the second argument here:	        lwz r4,[toc].GS.0.static_int(rtoc)                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^	     The argument following the `]' must be a symbol name, and the              register must be the toc register: 'rtoc' or '2'	     The effect is to 0 as the displacement field	     in the instruction, and issue an IMAGE_REL_PPC_TOCREL16 (or	     the appropriate variation) reloc against it based on the symbol.	     The linker will build the toc, and insert the resolved toc offset.	     Note:	     o The size of the toc entry is currently assumed to be	       32 bits. This should not be assumed to be a hard coded	       number.	     o In an effort to cope with a change from 32 to 64 bits,	       there are also toc entries that are specified to be	       either 32 or 64 bits:                 lwz r4,[toc32].GS.0.static_int(rtoc)	         lwz r4,[toc64].GS.0.static_int(rtoc)	       These demand toc entries of the specified size, and the	       instruction probably requires it.          */	  int valid_toc;	  enum toc_size_qualifier toc_kind;	  bfd_reloc_code_real_type toc_reloc;	  /* go parse off the [tocXX] part */	  valid_toc = parse_toc_entry(&toc_kind);	  if (!valid_toc) 	    {	      /* Note: message has already been issued.     */	      /* FIXME: what sort of recovery should we do? */	      /*        demand_rest_of_line(); return; ?    */	    }	  /* Now get the symbol following the ']' */	  expression(&ex);	  switch (toc_kind)	    {	    case default_toc:	      /* In this case, we may not have seen the symbol yet, since  */	      /* it is allowed to appear on a .extern or .globl or just be */	      /* a label in the .data section.                             */	      toc_reloc = BFD_RELOC_PPC_TOC16;	      break;	    case data_in_toc:	      /* 1. The symbol must be defined and either in the toc        */	      /*    section, or a global.                                   */	      /* 2. The reloc generated must have the TOCDEFN flag set in   */	      /*    upper bit mess of the reloc type.                       */	      /* FIXME: It's a little confusing what the tocv qualifier can */	      /*        be used for. At the very least, I've seen three     */	      /*        uses, only one of which I'm sure I can explain.     */	      if (ex.X_op == O_symbol) 		{		  		  assert (ex.X_add_symbol != NULL);		  if (ex.X_add_symbol->bsym->section != tocdata_section)		    {		      as_warn("[tocv] symbol is not a toc symbol");		    }		}	      toc_reloc = BFD_RELOC_PPC_TOC16;	      break;	    case must_be_32:	      /* FIXME: these next two specifically specify 32/64 bit toc   */	      /*        entries. We don't support them today. Is this the   */	      /*        right way to say that?                              */	      toc_reloc = BFD_RELOC_UNUSED;	      as_bad ("Unimplemented toc32 expression modifier");	      break;	    case must_be_64:	      /* FIXME: see above */	      toc_reloc = BFD_RELOC_UNUSED;	      as_bad ("Unimplemented toc64 expression modifier");	      break;	    default:	      fprintf(stderr, 		      "Unexpected return value [%d] from parse_toc_entry!\n",		      toc_kind);	      abort();	      break;	    }	  /* We need to generate a fixup for this expression.  */	  if (fc >= MAX_INSN_FIXUPS)	    as_fatal ("too many fixups");	  fixups[fc].reloc = toc_reloc;	  fixups[fc].exp = ex;	  fixups[fc].opindex = *opindex_ptr;	  ++fc;          /* Ok. We've set up the fixup for the instruction. Now make it	     look like the constant 0 was found here */	  ex.X_unsigned = 1;	  ex.X_op = O_constant;	  ex.X_add_number = 0;	  ex.X_add_symbol = NULL;	  ex.X_op_symbol = NULL;	}      else	{	  if (!register_name(&ex))	    {	      expression (&ex);	    }	}      str = input_line_pointer;      input_line_pointer = hold;#else      expression (&ex);      str = input_line_pointer;      input_line_pointer = hold;#endif      if (ex.X_op == O_illegal)	as_bad ("illegal operand");      else if (ex.X_op == O_absent)	as_bad ("missing operand");      else if (ex.X_op == O_constant)	{#ifdef OBJ_ELF	  /* Allow @HA, @L, @H on constants. */	  char *orig_str = str;	  if ((reloc = ppc_elf_suffix (&str)) != BFD_RELOC_UNUSED)	    switch (reloc)	      {	      default:		str = orig_str;		break;	      case BFD_RELOC_LO16:		ex.X_add_number = ((ex.X_add_number & 0xffff) ^ 0x8000) - 0x8000;		break;	      case BFD_RELOC_HI16:		ex.X_add_number = (ex.X_add_number >> 16) & 0xffff;		break;	      case BFD_RELOC_HI16_S:		ex.X_add_number = ((ex.X_add_number >> 16) & 0xffff)		  + ((ex.X_add_number >> 15) & 1);		break;	      }#endif	  insn = ppc_insert_operand (insn, operand, ex.X_add_number,				     (char *) NULL, 0);	}#ifdef TE_PE      else if (ex.X_op == O_register)	{	  insn = ppc_insert_operand (insn, operand, ex.X_add_number,				     (char *) NULL, 0);	}#endif#ifdef OBJ_ELF      else if ((reloc = ppc_elf_suffix (&str)) != BFD_RELOC_UNUSED)	{	  /* For the absoulte forms of branchs, convert the PC relative form back into	     the absolute.  */	  if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)	    switch (reloc)	      {	      case BFD_RELOC_PPC_B26:		reloc = BFD_RELOC_PPC_BA26;		break;	      case BFD_RELOC_PPC_B16:		reloc = BFD_RELOC_PPC_BA16;		break;	      case BFD_RELOC_PPC_B16_BRTAKEN:	reloc = BFD_RELOC_PPC_BA16_BRTAKEN;	break;	      case BFD_RELOC_PPC_B16_BRNTAKEN:	reloc = BFD_RELOC_PPC_BA16_BRNTAKEN;	break;	      }	  /* We need to generate a fixup for this expression.  */	  if (fc >= MAX_INSN_FIXUPS)	    as_fatal ("too many fixups");	  fixups[fc].exp = ex;	  fixups[fc].opindex = 0;	  fixups[fc].reloc = reloc;	  ++fc;	}#endif /* OBJ_ELF */      else	{	  /* We need to generate a fixup for this expression.  */	  if (fc >= MAX_INSN_FIXUPS)	    as_fatal ("too many fixups");	  fixups[fc].exp = ex;	  fixups[fc].opindex = *opindex_ptr;	  fixups[fc].reloc = BFD_RELOC_UNUSED;	  ++fc;	}      if (need_paren)	{	  endc = ')';	  need_paren = 0;	}      else if ((operand->flags & PPC_OPERAND_PARENS) != 0)	{	  endc = '(';	  need_paren = 1;	}      else	endc = ',';      /* The call to expression should have advanced str past any	 whitespace.  */      if (*str != endc	  && (endc != ',' || *str != '\0'))	{	  as_bad ("syntax error; found `%c' but expected `%c'", *str, endc);	  break;	}      if (*str != '\0')	++str;    }  while (isspace (*str))    ++str;  if (*str != '\0')    as_bad ("junk at end of line: `%s'", str);  /* Write out the instruction.  */  f = frag_more (4);  md_number_to_chars (f, insn, 4);  /* Create any fixups.  At this point we do not use a     bfd_reloc_code_real_type, but instead just use the     BFD_RELOC_UNUSED plus the operand index.  This lets us easily     handle fixups for any operand type, although that is admittedly     not a very exciting feature.  We pick a BFD reloc type in     md_apply_fix.  */  for (i = 0; i < fc; i++)    {      const struct powerpc_operand *operand;      operand = &powerpc_operands[fixups[i].opindex];      if (fixups[i].reloc != BFD_RELOC_UNUSED)	{	  reloc_howto_type *reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);	  int size;	  int offset;	  fixS *fixP;	  if (!reloc_howto)	    abort ();	  size = bfd_get_reloc_size (reloc_howto);	  offset = target_big_endian ? (4 - size) : 0;	  if (size < 1 || size > 4)	    abort();	  fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset, size,			      &fixups[i].exp, reloc_howto->pc_relative,			      fixups[i].reloc);	  /* Turn off complaints that the addend is too large for things like	     foo+100000@ha.  */	  switch (fixups[i].reloc)	    {	    case BFD_RELOC_LO16:	    case BFD_RELOC_HI16:	    case BFD_RELOC_HI16_S:	      fixP->fx_no_overflow = 1;	      break;	    default:	      break;	    }	}      else	fix_new_exp (frag_now, f - frag_now->fr_literal, 4,		     &fixups[i].exp,		     (operand->flags & PPC_OPERAND_RELATIVE) != 0,		     ((bfd_reloc_code_real_type)		       (fixups[i].opindex + (int) BFD_RELOC_UNUSED)));    }}