if (offset_expr.X_add_number != 0
if ((valueT) offset_expr.X_add_number >= MAX_GPREL_OFFSET
macro (ip)     struct mips_cl_insn *ip;{  register int treg, sreg, dreg, breg;  int tempreg;  int mask;  int icnt = 0;  int used_at;  expressionS expr1;  const char *s;  const char *s2;  const char *fmt;  int likely = 0;  int dbl = 0;  int coproc = 0;  int lr = 0;  offsetT maxnum;  int off;  bfd_reloc_code_real_type r;  char *p;  int hold_mips_optimize;  treg = (ip->insn_opcode >> 16) & 0x1f;  dreg = (ip->insn_opcode >> 11) & 0x1f;  sreg = breg = (ip->insn_opcode >> 21) & 0x1f;  mask = ip->insn_mo->mask;  expr1.X_op = O_constant;  expr1.X_op_symbol = NULL;  expr1.X_add_symbol = NULL;  expr1.X_add_number = 1;  switch (mask)    {    case M_DABS:      dbl = 1;    case M_ABS:      /* bgez $a0,.+12	 move v0,$a0	 sub v0,$zero,$a0	 */      mips_emit_delays ();      ++mips_noreorder;      mips_any_noreorder = 1;      expr1.X_add_number = 8;      macro_build ((char *) NULL, &icnt, &expr1, "bgez", "s,p", sreg);      if (dreg == sreg)	macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);      else	macro_build ((char *) NULL, &icnt, NULL, "move", "d,s", dreg, sreg, 0);      macro_build ((char *) NULL, &icnt, NULL,		   dbl ? "dsub" : "sub",		   "d,v,t", dreg, 0, sreg);      --mips_noreorder;      return;    case M_ADD_I:      s = "addi";      s2 = "add";      goto do_addi;    case M_ADDU_I:      s = "addiu";      s2 = "addu";      goto do_addi;    case M_DADD_I:      dbl = 1;      s = "daddi";      s2 = "dadd";      goto do_addi;    case M_DADDU_I:      dbl = 1;      s = "daddiu";      s2 = "daddu";    do_addi:      if (imm_expr.X_add_number >= -0x8000 && imm_expr.X_add_number < 0x8000)	{	  macro_build ((char *) NULL, &icnt, &imm_expr, s, "t,r,j", treg, sreg,		       (int) BFD_RELOC_LO16);	  return;	}      load_register (&icnt, AT, &imm_expr, dbl);      macro_build ((char *) NULL, &icnt, NULL, s2, "d,v,t", treg, sreg, AT);      break;    case M_AND_I:      s = "andi";      s2 = "and";      goto do_bit;    case M_OR_I:      s = "ori";      s2 = "or";      goto do_bit;    case M_NOR_I:      s = "";      s2 = "nor";      goto do_bit;    case M_XOR_I:      s = "xori";      s2 = "xor";    do_bit:      if (imm_expr.X_add_number >= 0 && imm_expr.X_add_number < 0x10000)	{	  if (mask != M_NOR_I)	    macro_build ((char *) NULL, &icnt, &imm_expr, s, "t,r,i", treg,			 sreg, (int) BFD_RELOC_LO16);	  else	    {	      macro_build ((char *) NULL, &icnt, &imm_expr, "ori", "t,r,i",			   treg, sreg, (int) BFD_RELOC_LO16);	      macro_build ((char *) NULL, &icnt, NULL, "nor", "d,v,t",			   treg, treg, 0);	    }	  return;	}      load_register (&icnt, AT, &imm_expr, 0);      macro_build ((char *) NULL, &icnt, NULL, s2, "d,v,t", treg, sreg, AT);      break;    case M_BEQ_I:      s = "beq";      goto beq_i;    case M_BEQL_I:      s = "beql";      likely = 1;      goto beq_i;    case M_BNE_I:      s = "bne";      goto beq_i;    case M_BNEL_I:      s = "bnel";      likely = 1;    beq_i:      if (imm_expr.X_add_number == 0)	{	  macro_build ((char *) NULL, &icnt, &offset_expr, s, "s,t,p", sreg,		       0);	  return;	}      load_register (&icnt, AT, &imm_expr, 0);      macro_build ((char *) NULL, &icnt, &offset_expr, s, "s,t,p", sreg, AT);      break;    case M_BGEL:      likely = 1;    case M_BGE:      if (treg == 0)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       likely ? "bgezl" : "bgez",		       "s,p", sreg);	  return;	}      if (sreg == 0)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       likely ? "blezl" : "blez",		       "s,p", treg);	  return;	}      macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", AT, sreg, treg);      macro_build ((char *) NULL, &icnt, &offset_expr,		   likely ? "beql" : "beq",		   "s,t,p", AT, 0);      break;    case M_BGTL_I:      likely = 1;    case M_BGT_I:      /* check for > max integer */      maxnum = 0x7fffffff;      if (mips_isa >= 3)	{	  maxnum <<= 16;	  maxnum |= 0xffff;	  maxnum <<= 16;	  maxnum |= 0xffff;	}      if (imm_expr.X_add_number >= maxnum	  && (mips_isa < 3 || sizeof (maxnum) > 4))	{	do_false:	  /* result is always false */	  if (! likely)	    {	      as_warn ("Branch %s is always false (nop)", ip->insn_mo->name);	      macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);	    }	  else	    {	      as_warn ("Branch likely %s is always false", ip->insn_mo->name);	      macro_build ((char *) NULL, &icnt, &offset_expr, "bnel",			   "s,t,p", 0, 0);	    }	  return;	}      imm_expr.X_add_number++;      /* FALLTHROUGH */    case M_BGE_I:    case M_BGEL_I:      if (mask == M_BGEL_I)	likely = 1;      if (imm_expr.X_add_number == 0)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       likely ? "bgezl" : "bgez",		       "s,p", sreg);	  return;	}      if (imm_expr.X_add_number == 1)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       likely ? "bgtzl" : "bgtz",		       "s,p", sreg);	  return;	}      maxnum = 0x7fffffff;      if (mips_isa >= 3)	{	  maxnum <<= 16;	  maxnum |= 0xffff;	  maxnum <<= 16;	  maxnum |= 0xffff;	}      maxnum = - maxnum - 1;      if (imm_expr.X_add_number <= maxnum	  && (mips_isa < 3 || sizeof (maxnum) > 4))	{	do_true:	  /* result is always true */	  as_warn ("Branch %s is always true", ip->insn_mo->name);	  macro_build ((char *) NULL, &icnt, &offset_expr, "b", "p");	  return;	}      set_at (&icnt, sreg, 0);      macro_build ((char *) NULL, &icnt, &offset_expr,		   likely ? "beql" : "beq",		   "s,t,p", AT, 0);      break;    case M_BGEUL:      likely = 1;    case M_BGEU:      if (treg == 0)	goto do_true;      if (sreg == 0)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       likely ? "beql" : "beq",		       "s,t,p", 0, treg);	  return;	}      macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", AT, sreg,		   treg);      macro_build ((char *) NULL, &icnt, &offset_expr,		   likely ? "beql" : "beq",		   "s,t,p", AT, 0);      break;    case M_BGTUL_I:      likely = 1;    case M_BGTU_I:      if (sreg == 0 || imm_expr.X_add_number == -1)	goto do_false;      imm_expr.X_add_number++;      /* FALLTHROUGH */    case M_BGEU_I:    case M_BGEUL_I:      if (mask == M_BGEUL_I)	likely = 1;      if (imm_expr.X_add_number == 0)	goto do_true;      if (imm_expr.X_add_number == 1)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       likely ? "bnel" : "bne",		       "s,t,p", sreg, 0);	  return;	}      set_at (&icnt, sreg, 1);      macro_build ((char *) NULL, &icnt, &offset_expr,		   likely ? "beql" : "beq",		   "s,t,p", AT, 0);      break;    case M_BGTL:      likely = 1;    case M_BGT:      if (treg == 0)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       likely ? "bgtzl" : "bgtz",		       "s,p", sreg);	  return;	}      if (sreg == 0)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       likely ? "bltzl" : "bltz",		       "s,p", treg);	  return;	}      macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", AT, treg, sreg);      macro_build ((char *) NULL, &icnt, &offset_expr,		   likely ? "bnel" : "bne",		   "s,t,p", AT, 0);      break;    case M_BGTUL:      likely = 1;    case M_BGTU:      if (treg == 0)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       likely ? "bnel" : "bne",		       "s,t,p", sreg, 0);	  return;	}      if (sreg == 0)	goto do_false;      macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", AT, treg,		   sreg);      macro_build ((char *) NULL, &icnt, &offset_expr,		   likely ? "bnel" : "bne",		   "s,t,p", AT, 0);      break;    case M_BLEL:      likely = 1;    case M_BLE:      if (treg == 0)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       likely ? "blezl" : "blez",		       "s,p", sreg);	  return;	}      if (sreg == 0)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       likely ? "bgezl" : "bgez",		       "s,p", treg);	  return;	}      macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", AT, treg, sreg);      macro_build ((char *) NULL, &icnt, &offset_expr,		   likely ? "beql" : "beq",		   "s,t,p", AT, 0);      break;    case M_BLEL_I:      likely = 1;    case M_BLE_I:      maxnum = 0x7fffffff;      if (mips_isa >= 3)	{	  maxnum <<= 16;	  maxnum |= 0xffff;	  maxnum <<= 16;	  maxnum |= 0xffff;	}      if (imm_expr.X_add_number >= maxnum	  && (mips_isa < 3 || sizeof (maxnum) > 4))	goto do_true;      imm_expr.X_add_number++;      /* FALLTHROUGH */    case M_BLT_I:    case M_BLTL_I:      if (mask == M_BLTL_I)	likely = 1;      if (imm_expr.X_add_number == 0)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       likely ? "bltzl" : "bltz",		       "s,p", sreg);	  return;	}      if (imm_expr.X_add_number == 1)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       likely ? "blezl" : "blez",		       "s,p", sreg);	  return;	}      set_at (&icnt, sreg, 0);      macro_build ((char *) NULL, &icnt, &offset_expr,		   likely ? "bnel" : "bne",		   "s,t,p", AT, 0);      break;    case M_BLEUL:      likely = 1;    case M_BLEU:      if (treg == 0)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       likely ? "beql" : "beq",		       "s,t,p", sreg, 0);	  return;	}      if (sreg == 0)	goto do_true;      macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", AT, treg,		   sreg);      macro_build ((char *) NULL, &icnt, &offset_expr,		   likely ? "beql" : "beq",		   "s,t,p", AT, 0);      break;    case M_BLEUL_I:      likely = 1;    case M_BLEU_I:      if (sreg == 0 || imm_expr.X_add_number == -1)	goto do_true;      imm_expr.X_add_number++;      /* FALLTHROUGH */    case M_BLTU_I:    case M_BLTUL_I:      if (mask == M_BLTUL_I)	likely = 1;      if (imm_expr.X_add_number == 0)	goto do_false;      if (imm_expr.X_add_number == 1)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       likely ? "beql" : "beq",		       "s,t,p", sreg, 0);	  return;	}      set_at (&icnt, sreg, 1);      macro_build ((char *) NULL, &icnt, &offset_expr,		   likely ? "bnel" : "bne",		   "s,t,p", AT, 0);      break;    case M_BLTL:      likely = 1;    case M_BLT:      if (treg == 0)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       likely ? "bltzl" : "bltz",		       "s,p", sreg);	  return;	}      if (sreg == 0)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       likely ? "bgtzl" : "bgtz",		       "s,p", treg);	  return;	}      macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", AT, sreg, treg);      macro_build ((char *) NULL, &icnt, &offset_expr,		   likely ? "bnel" : "bne",		   "s,t,p", AT, 0);      break;    case M_BLTUL:      likely = 1;    case M_BLTU:      if (treg == 0)	goto do_false;      if (sreg == 0)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       likely ? "bnel" : "bne",		       "s,t,p", 0, treg);	  return;	}      macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", AT, sreg,		   treg);      macro_build ((char *) NULL, &icnt, &offset_expr,		   likely ? "bnel" : "bne",		   "s,t,p", AT, 0);      break;    case M_DDIV_3:      dbl = 1;    case M_DIV_3:      s = "mflo";      goto do_div3;    case M_DREM_3:      dbl = 1;    case M_REM_3:      s = "mfhi";    do_div3:      if (treg == 0)	{	  as_warn ("Divide by zero.");	  if (mips_trap)	    macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", 0, 0);	  else	    macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);	  return;	}      mips_emit_delays ();      ++mips_noreorder;      mips_any_noreorder = 1;      macro_build ((char *) NULL, &icnt, NULL,		   dbl ? "ddiv" : "div",		   "z,s,t", sreg, treg);      if (mips_trap)	macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", treg, 0);      else	{	  expr1.X_add_number = 8;	  macro_build ((char *) NULL, &icnt, &expr1, "bne", "s,t,p", treg, 0);	  macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);	  macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);	}      expr1.X_add_number = -1;      macro_build ((char *) NULL, &icnt, &expr1,		   dbl ? "daddiu" : "addiu",		   "t,r,j", AT, 0, (int) BFD_RELOC_LO16);      expr1.X_add_number = mips_trap ? (dbl ? 12 : 8) : (dbl ? 20 : 16);      macro_build ((char *) NULL, &icnt, &expr1, "bne", "s,t,p", treg, AT);      if (dbl)	{	  expr1.X_add_number = 1;	  macro_build ((char *) NULL, &icnt, &expr1, "daddiu", "t,r,j", AT, 0,		       (int) BFD_RELOC_LO16);	  macro_build ((char *) NULL, &icnt, NULL, "dsll32", "d,w,<", AT, AT,		       31);	}      else	{	  expr1.X_add_number = 0x80000000;	  macro_build ((char *) NULL, &icnt, &expr1, "lui", "t,u", AT,		       (int) BFD_RELOC_HI16);	}      if (mips_trap)	macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", sreg, AT);      else	{	  expr1.X_add_number = 8;	  macro_build ((char *) NULL, &icnt, &expr1, "bne", "s,t,p", sreg, AT);	  macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);	  macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);	}      --mips_noreorder;      macro_build ((char *) NULL, &icnt, NULL, s, "d", dreg);      break;    case M_DIV_3I:      s = "div";      s2 = "mflo";      goto do_divi;    case M_DIVU_3I:      s = "divu";      s2 = "mflo";      goto do_divi;    case M_REM_3I:      s = "div";      s2 = "mfhi";      goto do_divi;    case M_REMU_3I:      s = "divu";      s2 = "mfhi";      goto do_divi;    case M_DDIV_3I:      dbl = 1;      s = "ddiv";      s2 = "mflo";      goto do_divi;    case M_DDIVU_3I:      dbl = 1;      s = "ddivu";      s2 = "mflo";      goto do_divi;    case M_DREM_3I:      dbl = 1;      s = "ddiv";      s2 = "mfhi";      goto do_divi;    case M_DREMU_3I:      dbl = 1;      s = "ddivu";      s2 = "mfhi";    do_divi:      if (imm_expr.X_add_number == 0)	{	  as_warn ("Divide by zero.");	  if (mips_trap)	    macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", 0, 0);	  else	    macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);	  return;	}      if (imm_expr.X_add_number == 1)	{	  if (strcmp (s2, "mflo") == 0)	    macro_build ((char *) NULL, &icnt, NULL, "move", "d,s", dreg,			 sreg);	  else	    macro_build ((char *) NULL, &icnt, NULL, "move", "d,s", dreg, 0);	  return;	}      if (imm_expr.X_add_number == -1	  && s[strlen (s) - 1] != 'u')	{	  if (strcmp (s2, "mflo") == 0)	    {	      if (dbl)		macro_build ((char *) NULL, &icnt, NULL, "dneg", "d,w", dreg,			     sreg);	      else		macro_build ((char *) NULL, &icnt, NULL, "neg", "d,w", dreg,			     sreg);	    }	  else	    macro_build ((char *) NULL, &icnt, NULL, "move", "d,s", dreg, 0);	  return;	}      load_register (&icnt, AT, &imm_expr, dbl);      macro_build ((char *) NULL, &icnt, NULL, s, "z,s,t", sreg, AT);      macro_build ((char *) NULL, &icnt, NULL, s2, "d", dreg);      break;    case M_DIVU_3:      s = "divu";      s2 = "mflo";      goto do_divu3;    case M_REMU_3:      s = "divu";      s2 = "mfhi";      goto do_divu3;    case M_DDIVU_3:      s = "ddivu";      s2 = "mflo";      goto do_divu3;    case M_DREMU_3:      s = "ddivu";      s2 = "mfhi";    do_divu3:      mips_emit_delays ();      ++mips_noreorder;      mips_any_noreorder = 1;      macro_build ((char *) NULL, &icnt, NULL, s, "z,s,t", sreg, treg);      if (mips_trap)	macro_build ((char *) NULL, &icnt, NULL, "teq", "s,t", treg, 0);      else	{	  expr1.X_add_number = 8;	  macro_build ((char *) NULL, &icnt, &expr1, "bne", "s,t,p", treg, 0);	  macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);	  macro_build ((char *) NULL, &icnt, NULL, "break", "c", 7);	}      --mips_noreorder;      macro_build ((char *) NULL, &icnt, NULL, s2, "d", dreg);      return;    case M_DLA_AB:      dbl = 1;    case M_LA_AB:      /* Load the address of a symbol into a register.  If breg is not	 zero, we then add a base register to it.  */      /* When generating embedded PIC code, we permit expressions of	 the form	   la	$4,foo-bar	 where bar is an address in the .text section.  These are used	 when getting the addresses of functions.  We don't permit	 X_add_number to be non-zero, because if the symbol is	 external the relaxing code needs to know that any addend is	 purely the offset to X_op_symbol.  */      if (mips_pic == EMBEDDED_PIC	  && offset_expr.X_op == O_subtract	  && now_seg == text_section	  && (offset_expr.X_op_symbol->sy_value.X_op == O_constant	      ? S_GET_SEGMENT (offset_expr.X_op_symbol) == text_section	      : (offset_expr.X_op_symbol->sy_value.X_op == O_symbol		 && (S_GET_SEGMENT (offset_expr.X_op_symbol				    ->sy_value.X_add_symbol)		     == text_section)))	  && breg == 0	  && offset_expr.X_add_number == 0)	{	  macro_build ((char *) NULL, &icnt, &offset_expr, "lui", "t,u",		       treg, (int) BFD_RELOC_PCREL_HI16_S);	  macro_build ((char *) NULL, &icnt, &offset_expr,		       mips_isa < 3 ? "addiu" : "daddiu",		       "t,r,j", treg, treg, (int) BFD_RELOC_PCREL_LO16);	  return;	}      if (offset_expr.X_op != O_symbol	  && offset_expr.X_op != O_constant)	{	  as_bad ("expression too complex");	  offset_expr.X_op = O_constant;	}      if (treg == breg)	{	  tempreg = AT;	  used_at = 1;	}      else	{	  tempreg = treg;	  used_at = 0;	}      if (offset_expr.X_op == O_constant)	load_register (&icnt, tempreg, &offset_expr, dbl);      else if (mips_pic == NO_PIC)	{	  /* If this is a reference to an GP relative symbol, we want	       addiu	$tempreg,$gp,<sym>	(BFD_RELOC_MIPS_GPREL)	     Otherwise we want	       lui	$tempreg,<sym>		(BFD_RELOC_HI16_S)	       addiu	$tempreg,$tempreg,<sym>	(BFD_RELOC_LO16)	     If we have a constant, we need two instructions anyhow,	     so we may as well always use the latter form.  */	  if (offset_expr.X_add_number != 0	      || nopic_need_relax (offset_expr.X_add_symbol))	    p = NULL;	  else	    {	      frag_grow (20);	      macro_build ((char *) NULL, &icnt, &offset_expr,			   mips_isa < 3 ? "addiu" : "daddiu",			   "t,r,j", tempreg, GP, (int) BFD_RELOC_MIPS_GPREL);	      p = frag_var (rs_machine_dependent, 8, 0,			    RELAX_ENCODE (4, 8, 0, 4, 0,					  mips_warn_about_macros),			    offset_expr.X_add_symbol, (long) 0,			    (char *) NULL);	    }	  macro_build_lui (p, &icnt, &offset_expr, tempreg);	  if (p != NULL)	    p += 4;	  macro_build (p, &icnt, &offset_expr,		       mips_isa < 3 ? "addiu" : "daddiu",		       "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);	}      else if (mips_pic == SVR4_PIC)	{	  /* If this is a reference to an external symbol, and there	     is no constant, we want	       lw	$tempreg,<sym>($gp)	(BFD_RELOC_MIPS_GOT16)	     For a local symbol, we want	       lw	$tempreg,<sym>($gp)	(BFD_RELOC_MIPS_GOT16)	       nop	       addiu	$tempreg,$tempreg,<sym>	(BFD_RELOC_LO16)	     If we have a small constant, and this is a reference to	     an external symbol, we want	       lw	$tempreg,<sym>($gp)	(BFD_RELOC_MIPS_GOT16)	       nop	       addiu	$tempreg,$tempreg,<constant>	     For a local symbol, we want the same instruction	     sequence, but we output a BFD_RELOC_LO16 reloc on the	     addiu instruction.	     If we have a large constant, and this is a reference to	     an external symbol, we want	       lw	$tempreg,<sym>($gp)	(BFD_RELOC_MIPS_GOT16)	       lui	$at,<hiconstant>	       addiu	$at,$at,<loconstant>	       addu	$tempreg,$tempreg,$at	     For a local symbol, we want the same instruction	     sequence, but we output a BFD_RELOC_LO16 reloc on the	     addiu instruction.  */	  expr1.X_add_number = offset_expr.X_add_number;	  offset_expr.X_add_number = 0;	  frag_grow (32);	  macro_build ((char *) NULL, &icnt, &offset_expr,		       dbl ? "ld" : "lw",		       "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16, GP);	  if (expr1.X_add_number == 0)	    {	      int off;	      if (breg == 0)		off = 0;	      else		{		  /* We're going to put in an addu instruction using		     tempreg, so we may as well insert the nop right		     now.  */		  macro_build ((char *) NULL, &icnt, (expressionS *) NULL,			       "nop", "");		  off = 4;		}	      p = frag_var (rs_machine_dependent, 8 - off, 0,			    RELAX_ENCODE (0, 8 - off, -4 - off, 4 - off, 0,					  (breg == 0					   ? mips_warn_about_macros					   : 0)),			    offset_expr.X_add_symbol, (long) 0,			    (char *) NULL);	      if (breg == 0)		{		  macro_build (p, &icnt, (expressionS *) NULL, "nop", "");		  p += 4;		}	      macro_build (p, &icnt, &expr1,			   mips_isa < 3 ? "addiu" : "daddiu",			   "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);	      /* FIXME: If breg == 0, and the next instruction uses		 $tempreg, then if this variant case is used an extra		 nop will be generated.  */	    }	  else if (expr1.X_add_number >= -0x8000		   && expr1.X_add_number < 0x8000)	    {	      macro_build ((char *) NULL, &icnt, (expressionS *) NULL,			   "nop", "");	      macro_build ((char *) NULL, &icnt, &expr1,			   mips_isa < 3 ? "addiu" : "daddiu",			   "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);	      (void) frag_var (rs_machine_dependent, 0, 0,			       RELAX_ENCODE (0, 0, -12, -4, 0, 0),			       offset_expr.X_add_symbol, (long) 0,			       (char *) NULL);	    }	  else	    {	      int off1;	      /* If we are going to add in a base register, and the		 target register and the base register are the same,		 then we are using AT as a temporary register.  Since		 we want to load the constant into AT, we add our		 current AT (from the global offset table) and the		 register into the register now, and pretend we were		 not using a base register.  */	      if (breg != treg)		off1 = 0;	      else		{		  macro_build ((char *) NULL, &icnt, (expressionS *) NULL,			       "nop", "");		  macro_build ((char *) NULL, &icnt, (expressionS *) NULL,			       mips_isa < 3 ? "addu" : "daddu",			       "d,v,t", treg, AT, breg);		  breg = 0;		  tempreg = treg;		  off1 = -8;		}	      /* Set mips_optimize around the lui instruction to avoid		 inserting an unnecessary nop after the lw.  */	      hold_mips_optimize = mips_optimize;	      mips_optimize = 2;	      macro_build_lui ((char *) NULL, &icnt, &expr1, AT);	      mips_optimize = hold_mips_optimize;	      macro_build ((char *) NULL, &icnt, &expr1,			   mips_isa < 3 ? "addiu" : "daddiu",			   "t,r,j", AT, AT, (int) BFD_RELOC_LO16);	      macro_build ((char *) NULL, &icnt, (expressionS *) NULL,			   mips_isa < 3 ? "addu" : "daddu",			   "d,v,t", tempreg, tempreg, AT);	      (void) frag_var (rs_machine_dependent, 0, 0,			       RELAX_ENCODE (0, 0, -16 + off1, -8, 0, 0),			       offset_expr.X_add_symbol, (long) 0,			       (char *) NULL);	      used_at = 1;	    }	}      else if (mips_pic == EMBEDDED_PIC)	{	  /* We use	       addiu	$tempreg,$gp,<sym>	(BFD_RELOC_MIPS_GPREL)	     */	  macro_build ((char *) NULL, &icnt, &offset_expr,		       mips_isa < 3 ? "addiu" : "daddiu",		       "t,r,j", tempreg, GP, (int) BFD_RELOC_MIPS_GPREL);	}      else	abort ();      if (breg != 0)	macro_build ((char *) NULL, &icnt, (expressionS *) NULL,		     mips_isa < 3 ? "addu" : "daddu",		     "d,v,t", treg, tempreg, breg);      if (! used_at)	return;      break;    case M_J_A:      /* The j instruction may not be used in PIC code, since it	 requires an absolute address.  We convert it to a b	 instruction.  */      if (mips_pic == NO_PIC)	macro_build ((char *) NULL, &icnt, &offset_expr, "j", "a");      else	macro_build ((char *) NULL, &icnt, &offset_expr, "b", "p");      return;      /* The jal instructions must be handled as macros because when	 generating PIC code they expand to multi-instruction	 sequences.  Normally they are simple instructions.  */    case M_JAL_1:      dreg = RA;      /* Fall through.  */    case M_JAL_2:      if (mips_pic == NO_PIC	  || mips_pic == EMBEDDED_PIC)	macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "jalr",		     "d,s", dreg, sreg);      else if (mips_pic == SVR4_PIC)	{	  if (sreg != PIC_CALL_REG)	    as_warn ("MIPS PIC call to register other than $25");      	  macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "jalr",		       "d,s", dreg, sreg);	  if (mips_cprestore_offset < 0)	    as_warn ("No .cprestore pseudo-op used in PIC code");	  else	    {	      expr1.X_add_number = mips_cprestore_offset;	      macro_build ((char *) NULL, &icnt, &expr1,			   mips_isa < 3 ? "lw" : "ld",			   "t,o(b)", GP, (int) BFD_RELOC_LO16, mips_frame_reg);	    }	}      else	abort ();      return;    case M_JAL_A:      if (mips_pic == NO_PIC)	macro_build ((char *) NULL, &icnt, &offset_expr, "jal", "a");      else if (mips_pic == SVR4_PIC)	{	  /* If this is a reference to an external symbol, we want	       lw	$25,<sym>($gp)		(BFD_RELOC_MIPS_CALL16)	       nop	       jalr	$25	       nop	       lw	$gp,cprestore($sp)	     The cprestore value is set using the .cprestore	     pseudo-op.  If the symbol is not external, we want	       lw	$25,<sym>($gp)		(BFD_RELOC_MIPS_GOT16)	       nop	       addiu	$25,$25,<sym>		(BFD_RELOC_LO16)	       jalr	$25	       nop	       lw	$gp,cprestore($sp)	     */	  frag_grow (20);	  macro_build ((char *) NULL, &icnt, &offset_expr,		       mips_isa < 3 ? "lw" : "ld",		       "t,o(b)", PIC_CALL_REG,		       (int) BFD_RELOC_MIPS_CALL16, GP);	  macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");	  p = frag_var (rs_machine_dependent, 4, 0,			RELAX_ENCODE (0, 4, -8, 0, 0, 0),			offset_expr.X_add_symbol, (long) 0, (char *) NULL);	  macro_build (p, &icnt, &offset_expr,		       mips_isa < 3 ? "addiu" : "daddiu",		       "t,r,j", PIC_CALL_REG, PIC_CALL_REG,		       (int) BFD_RELOC_LO16);	  macro_build ((char *) NULL, &icnt, (expressionS *) NULL,		       "jalr", "s", PIC_CALL_REG);	  if (mips_cprestore_offset < 0)	    as_warn ("No .cprestore pseudo-op used in PIC code");	  else	    {	      if (mips_noreorder)		macro_build ((char *) NULL, &icnt, (expressionS *) NULL,			     "nop", "");	      expr1.X_add_number = mips_cprestore_offset;	      macro_build ((char *) NULL, &icnt, &expr1,			   mips_isa < 3 ? "lw" : "ld",			   "t,o(b)", GP, (int) BFD_RELOC_LO16,			   mips_frame_reg);	    }	}      else if (mips_pic == EMBEDDED_PIC)	{	  macro_build ((char *) NULL, &icnt, &offset_expr, "bal", "p");	  /* The linker may expand the call to a longer sequence which	     uses $at, so we must break rather than return.  */	  break;	}      else	abort ();      return;    case M_LB_AB:      s = "lb";      goto ld;    case M_LBU_AB:      s = "lbu";      goto ld;    case M_LH_AB:      s = "lh";      goto ld;    case M_LHU_AB:      s = "lhu";      goto ld;    case M_LW_AB:      s = "lw";      goto ld;    case M_LWC0_AB:      s = "lwc0";      coproc = 1;      goto ld;    case M_LWC1_AB:      s = "lwc1";      coproc = 1;      goto ld;    case M_LWC2_AB:      s = "lwc2";      coproc = 1;      goto ld;    case M_LWC3_AB:      s = "lwc3";      coproc = 1;      goto ld;    case M_LWL_AB:      s = "lwl";      lr = 1;      goto ld;    case M_LWR_AB:      s = "lwr";      lr = 1;      goto ld;    case M_LDC1_AB:      s = "ldc1";      coproc = 1;      goto ld;    case M_LDC2_AB:      s = "ldc2";      coproc = 1;      goto ld;    case M_LDC3_AB:      s = "ldc3";      coproc = 1;      goto ld;    case M_LDL_AB:      s = "ldl";      lr = 1;      goto ld;    case M_LDR_AB:      s = "ldr";      lr = 1;      goto ld;    case M_LL_AB:      s = "ll";      goto ld;    case M_LLD_AB:      s = "lld";      goto ld;    case M_LWU_AB:      s = "lwu";    ld:      if (breg == treg || coproc || lr)	{	  tempreg = AT;	  used_at = 1;	}      else	{	  tempreg = treg;	  used_at = 0;	}      goto ld_st;    case M_SB_AB:      s = "sb";      goto st;    case M_SH_AB:      s = "sh";      goto st;    case M_SW_AB:      s = "sw";      goto st;    case M_SWC0_AB:      s = "swc0";      coproc = 1;      goto st;    case M_SWC1_AB:      s = "swc1";      coproc = 1;      goto st;    case M_SWC2_AB:      s = "swc2";      coproc = 1;      goto st;    case M_SWC3_AB:      s = "swc3";      coproc = 1;      goto st;    case M_SWL_AB:      s = "swl";      goto st;    case M_SWR_AB:      s = "swr";      goto st;    case M_SC_AB:      s = "sc";      goto st;    case M_SCD_AB:      s = "scd";      goto st;    case M_SDC1_AB:      s = "sdc1";      coproc = 1;      goto st;    case M_SDC2_AB:      s = "sdc2";      coproc = 1;      goto st;    case M_SDC3_AB:      s = "sdc3";      coproc = 1;      goto st;    case M_SDL_AB:      s = "sdl";      goto st;    case M_SDR_AB:      s = "sdr";    st:      tempreg = AT;      used_at = 1;    ld_st:      if (mask == M_LWC1_AB	  || mask == M_SWC1_AB	  || mask == M_LDC1_AB	  || mask == M_SDC1_AB	  || mask == M_L_DAB	  || mask == M_S_DAB)	fmt = "T,o(b)";      else if (coproc)	fmt = "E,o(b)";      else	fmt = "t,o(b)";      if (offset_expr.X_op != O_constant	  && offset_expr.X_op != O_symbol)	{	  as_bad ("expression too complex");	  offset_expr.X_op = O_constant;	}      /* A constant expression in PIC code can be handled just as it	 is in non PIC code.  */      if (mips_pic == NO_PIC	  || offset_expr.X_op == O_constant)	{	  /* If this is a reference to a GP relative symbol, and there	     is no base register, we want	       <op>	$treg,<sym>($gp)	(BFD_RELOC_MIPS_GPREL)	     Otherwise, if there is no base register, we want	       lui	$tempreg,<sym>		(BFD_RELOC_HI16_S)	       <op>	$treg,<sym>($tempreg)	(BFD_RELOC_LO16)	     If we have a constant, we need two instructions anyhow,	     so we always use the latter form.	     If we have a base register, and this is a reference to a	     GP relative symbol, we want	       addu	$tempreg,$breg,$gp	       <op>	$treg,<sym>($tempreg)	(BFD_RELOC_MIPS_GPREL)	     Otherwise we want	       lui	$tempreg,<sym>		(BFD_RELOC_HI16_S)	       addu	$tempreg,$tempreg,$breg	       <op>	$treg,<sym>($tempreg)	(BFD_RELOC_LO16)	     With a constant we always use the latter case.  */	  if (breg == 0)	    {	      if (offset_expr.X_add_number != 0		  || nopic_need_relax (offset_expr.X_add_symbol))		p = NULL;	      else		{		  frag_grow (20);		  macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,			       treg, (int) BFD_RELOC_MIPS_GPREL, GP);		  p = frag_var (rs_machine_dependent, 8, 0,				RELAX_ENCODE (4, 8, 0, 4, 0,					      (mips_warn_about_macros					       || (used_at && mips_noat))),				offset_expr.X_add_symbol, (long) 0,				(char *) NULL);		  used_at = 0;		}	      macro_build_lui (p, &icnt, &offset_expr, tempreg);	      if (p != NULL)		p += 4;	      macro_build (p, &icnt, &offset_expr, s, fmt, treg,			   (int) BFD_RELOC_LO16, tempreg);	    }	  else	    {	      if (offset_expr.X_add_number != 0		  || nopic_need_relax (offset_expr.X_add_symbol))		p = NULL;	      else		{		  frag_grow (28);		  macro_build ((char *) NULL, &icnt, (expressionS *) NULL,			       mips_isa < 3 ? "addu" : "daddu",			       "d,v,t", tempreg, breg, GP);		  macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,			       treg, (int) BFD_RELOC_MIPS_GPREL, tempreg);		  p = frag_var (rs_machine_dependent, 12, 0,				RELAX_ENCODE (8, 12, 0, 8, 0, 0),				offset_expr.X_add_symbol, (long) 0,				(char *) NULL);		}	      macro_build_lui (p, &icnt, &offset_expr, tempreg);	      if (p != NULL)		p += 4;	      macro_build (p, &icnt, (expressionS *) NULL,			   mips_isa < 3 ? "addu" : "daddu",			   "d,v,t", tempreg, tempreg, breg);	      if (p != NULL)		p += 4;	      macro_build (p, &icnt, &offset_expr, s, fmt, treg,			   (int) BFD_RELOC_LO16, tempreg);	    }	}      else if (mips_pic == SVR4_PIC)	{	  /* If this is a reference to an external symbol, we want	       lw	$tempreg,<sym>($gp)	(BFD_RELOC_MIPS_GOT16)	       nop	       <op>	$treg,0($tempreg)	     Otherwise we want	       lw	$tempreg,<sym>($gp)	(BFD_RELOC_MIPS_GOT16)	       nop	       addiu	$tempreg,$tempreg,<sym>	(BFD_RELOC_LO16)	       <op>	$treg,0($tempreg)	     If there is a base register, we add it to $tempreg before	     the <op>.  If there is a constant, we stick it in the	     <op> instruction.  We don't handle constants larger than	     16 bits, because we have no way to load the upper 16 bits	     (actually, we could handle them for the subset of cases	     in which we are not using $at).  */	  assert (offset_expr.X_op == O_symbol);	  expr1.X_add_number = offset_expr.X_add_number;	  offset_expr.X_add_number = 0;	  if (expr1.X_add_number < -0x8000	      || expr1.X_add_number >= 0x8000)	    as_bad ("PIC code offset overflow (max 16 signed bits)");	  frag_grow (20);	  macro_build ((char *) NULL, &icnt, &offset_expr,		       mips_isa < 3 ? "lw" : "ld",		       "t,o(b)", tempreg, (int) BFD_RELOC_MIPS_GOT16, GP);	  macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");	  p = frag_var (rs_machine_dependent, 4, 0, 			RELAX_ENCODE (0, 4, -8, 0, 0, 0),			offset_expr.X_add_symbol, (long) 0,			(char *) NULL);	  macro_build (p, &icnt, &offset_expr,		       mips_isa < 3 ? "addiu" : "daddiu",		       "t,r,j", tempreg, tempreg, (int) BFD_RELOC_LO16);	  if (breg != 0)	    macro_build ((char *) NULL, &icnt, (expressionS *) NULL,			 mips_isa < 3 ? "addu" : "daddu",			 "d,v,t", tempreg, tempreg, breg);	  macro_build ((char *) NULL, &icnt, &expr1, s, fmt, treg,		       (int) BFD_RELOC_LO16, tempreg);	}      else if (mips_pic == EMBEDDED_PIC)	{	  /* If there is no base register, we want	       <op>	$treg,<sym>($gp)	(BFD_RELOC_MIPS_GPREL)	     If there is a base register, we want	       addu	$tempreg,$breg,$gp	       <op>	$treg,<sym>($tempreg)	(BFD_RELOC_MIPS_GPREL)	     */	  assert (offset_expr.X_op == O_symbol);	  if (breg == 0)	    {	      macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,			   treg, (int) BFD_RELOC_MIPS_GPREL, GP);	      used_at = 0;	    }	  else	    {	      macro_build ((char *) NULL, &icnt, (expressionS *) NULL,			   mips_isa < 3 ? "addu" : "daddu",			   "d,v,t", tempreg, breg, GP);	      macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,			   treg, (int) BFD_RELOC_MIPS_GPREL, tempreg);	    }	}      else	abort ();      if (! used_at)	return;      break;    case M_LI:    case M_LI_S:      load_register (&icnt, treg, &imm_expr, 0);      return;    case M_DLI:      load_register (&icnt, treg, &imm_expr, 1);      return;    case M_LI_SS:      if (imm_expr.X_op == O_constant)	{	  load_register (&icnt, AT, &imm_expr, 0);	  macro_build ((char *) NULL, &icnt, (expressionS *) NULL,		       "mtc1", "t,G", AT, treg);	  break;	}      else	{	  assert (offset_expr.X_op == O_symbol		  && strcmp (segment_name (S_GET_SEGMENT					   (offset_expr.X_add_symbol)),			     ".lit4") == 0		  && offset_expr.X_add_number == 0);	  macro_build ((char *) NULL, &icnt, &offset_expr, "lwc1", "T,o(b)",		       treg, (int) BFD_RELOC_MIPS_LITERAL, GP);	  return;	}    case M_LI_D:      /* We know that sym is in the .rdata section.  First we get the	 upper 16 bits of the address.  */      if (mips_pic == NO_PIC)	{	  /* FIXME: This won't work for a 64 bit address.  */	  macro_build_lui ((char *) NULL, &icnt, &offset_expr, AT);	}      else if (mips_pic == SVR4_PIC)	{	  macro_build ((char *) NULL, &icnt, &offset_expr,		       mips_isa < 3 ? "lw" : "ld",		       "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16, GP);	}      else if (mips_pic == EMBEDDED_PIC)	{	  /* For embedded PIC we pick up the entire address off $gp in	     a single instruction.  */	  macro_build ((char *) NULL, &icnt, &offset_expr,		       mips_isa < 3 ? "addiu" : "daddiu",		       "t,r,j", AT, GP, (int) BFD_RELOC_MIPS_GPREL);	  offset_expr.X_op = O_constant;	  offset_expr.X_add_number = 0;	}      else	abort ();	      /* Now we load the register(s).  */      if (mips_isa >= 3)	macro_build ((char *) NULL, &icnt, &offset_expr, "ld", "t,o(b)",		     treg, (int) BFD_RELOC_LO16, AT);      else	{	  macro_build ((char *) NULL, &icnt, &offset_expr, "lw", "t,o(b)",		       treg, (int) BFD_RELOC_LO16, AT);	  if (treg != 31)	    {	      /* FIXME: How in the world do we deal with the possible		 overflow here?  */	      offset_expr.X_add_number += 4;	      macro_build ((char *) NULL, &icnt, &offset_expr, "lw", "t,o(b)",			   treg + 1, (int) BFD_RELOC_LO16, AT);	    }	}      /* To avoid confusion in tc_gen_reloc, we must ensure that this	 does not become a variant frag.  */      frag_wane (frag_now);      frag_new (0);      break;    case M_LI_DD:      assert (offset_expr.X_op == O_symbol	      && offset_expr.X_add_number == 0);      s = segment_name (S_GET_SEGMENT (offset_expr.X_add_symbol));      if (strcmp (s, ".lit8") == 0)	{	  if (mips_isa >= 2)	    {	      macro_build ((char *) NULL, &icnt, &offset_expr, "ldc1",			   "T,o(b)", treg, (int) BFD_RELOC_MIPS_LITERAL, GP);	      return;	    }	  breg = GP;	  r = BFD_RELOC_MIPS_LITERAL;	  goto dob;	}      else	{	  assert (strcmp (s, RDATA_SECTION_NAME) == 0);	  if (mips_pic == SVR4_PIC)	    macro_build ((char *) NULL, &icnt, &offset_expr,			 mips_isa < 3 ? "lw" : "ld",			 "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16, GP);	  else	    {	      /* FIXME: This won't work for a 64 bit address.  */	      macro_build_lui ((char *) NULL, &icnt, &offset_expr, AT);	    }	      	  if (mips_isa >= 2)	    {	      macro_build ((char *) NULL, &icnt, &offset_expr, "ldc1",			   "T,o(b)", treg, (int) BFD_RELOC_LO16, AT);	      /* To avoid confusion in tc_gen_reloc, we must ensure		 that this does not become a variant frag.  */	      frag_wane (frag_now);	      frag_new (0);	      break;	    }	  breg = AT;	  r = BFD_RELOC_LO16;	  goto dob;	}    case M_L_DOB:      /* Even on a big endian machine $fn comes before $fn+1.  We have	 to adjust when loading from memory.  */      r = BFD_RELOC_LO16;    dob:      assert (mips_isa < 2);      macro_build ((char *) NULL, &icnt, &offset_expr, "lwc1", "T,o(b)",		   byte_order == LITTLE_ENDIAN ? treg : treg + 1,		   (int) r, breg);      /* FIXME: A possible overflow which I don't know how to deal	 with.  */      offset_expr.X_add_number += 4;      macro_build ((char *) NULL, &icnt, &offset_expr, "lwc1", "T,o(b)",		   byte_order == LITTLE_ENDIAN ? treg + 1 : treg,		   (int) r, breg);      /* To avoid confusion in tc_gen_reloc, we must ensure that this	 does not become a variant frag.  */      frag_wane (frag_now);      frag_new (0);      if (breg != AT)	return;      break;    case M_L_DAB:      /*       * The MIPS assembler seems to check for X_add_number not       * being double aligned and generating:       *	lui	at,%hi(foo+1)       *	addu	at,at,v1       *	addiu	at,at,%lo(foo+1)       *	lwc1	f2,0(at)       *	lwc1	f3,4(at)       * But, the resulting address is the same after relocation so why       * generate the extra instruction?       */      coproc = 1;      if (mips_isa >= 2)	{	  s = "ldc1";	  goto ld;	}      s = "lwc1";      fmt = "T,o(b)";      goto ldd_std;    case M_S_DAB:      if (mips_isa >= 2)	{	  s = "sdc1";	  goto st;	}      s = "swc1";      fmt = "T,o(b)";      coproc = 1;      goto ldd_std;    case M_LD_AB:      if (mips_isa >= 3)	{	  s = "ld";	  goto ld;	}      s = "lw";      fmt = "t,o(b)";      goto ldd_std;    case M_SD_AB:      if (mips_isa >= 3)	{	  s = "sd";	  goto st;	}      s = "sw";      fmt = "t,o(b)";    ldd_std:      if (offset_expr.X_op != O_symbol	  && offset_expr.X_op != O_constant)	{	  as_bad ("expression too complex");	  offset_expr.X_op = O_constant;	}      /* Even on a big endian machine $fn comes before $fn+1.  We have	 to adjust when loading from memory.  We set coproc if we must	 load $fn+1 first.  */      if (byte_order == LITTLE_ENDIAN)	coproc = 0;      if (mips_pic == NO_PIC	  || offset_expr.X_op == O_constant)	{	  /* If this is a reference to a GP relative symbol, we want	       <op>	$treg,<sym>($gp)	(BFD_RELOC_MIPS_GPREL)	       <op>	$treg+1,<sym>+4($gp)	(BFD_RELOC_MIPS_GPREL)	     If we have a base register, we use this	       addu	$at,$breg,$gp	       <op>	$treg,<sym>($at)	(BFD_RELOC_MIPS_GPREL)	       <op>	$treg+1,<sym>+4($at)	(BFD_RELOC_MIPS_GPREL)	     If this is not a GP relative symbol, we want	       lui	$at,<sym>		(BFD_RELOC_HI16_S)	       <op>	$treg,<sym>($at)	(BFD_RELOC_LO16)	       <op>	$treg+1,<sym>+4($at)	(BFD_RELOC_LO16)	     If there is a base register, we add it to $at after the	     lui instruction.  If there is a constant, we always use	     the last case.  */	  if (offset_expr.X_add_number != 0	      || nopic_need_relax (offset_expr.X_add_symbol))	    {	      p = NULL;	      used_at = 1;	    }	  else	    {	      int off;	      if (breg == 0)		{		  frag_grow (28);		  tempreg = GP;		  off = 0;		  used_at = 0;		}	      else		{		  frag_grow (36);		  macro_build ((char *) NULL, &icnt, (expressionS *) NULL,			       mips_isa < 3 ? "addu" : "daddu",			       "d,v,t", AT, breg, GP);		  tempreg = AT;		  off = 4;		  used_at = 1;		}	      macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,			   coproc ? treg + 1 : treg,			   (int) BFD_RELOC_MIPS_GPREL, tempreg);	      offset_expr.X_add_number += 4;	      /* Set mips_optimize to 2 to avoid inserting an                 undesired nop.  */	      hold_mips_optimize = mips_optimize;	      mips_optimize = 2;	      macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,			   coproc ? treg : treg + 1,			   (int) BFD_RELOC_MIPS_GPREL, tempreg);	      mips_optimize = hold_mips_optimize;	      p = frag_var (rs_machine_dependent, 12 + off, 0,			    RELAX_ENCODE (8 + off, 12 + off, 0, 4 + off, 1,					  used_at && mips_noat),			    offset_expr.X_add_symbol, (long) 0,			    (char *) NULL);	      /* We just generated two relocs.  When tc_gen_reloc		 handles this case, it will skip the first reloc and		 handle the second.  The second reloc already has an		 extra addend of 4, which we added above.  We must		 subtract it out, and then subtract another 4 to make		 the first reloc come out right.  The second reloc		 will come out right because we are going to add 4 to		 offset_expr when we build its instruction below.  */	      offset_expr.X_add_number -= 8;	      offset_expr.X_op = O_constant;	    }	  macro_build_lui (p, &icnt, &offset_expr, AT);	  if (p != NULL)	    p += 4;	  if (breg != 0)	    {	      macro_build (p, &icnt, (expressionS *) NULL,			   mips_isa < 3 ? "addu" : "daddu",			   "d,v,t", AT, breg, AT);	      if (p != NULL)		p += 4;	    }	  macro_build (p, &icnt, &offset_expr, s, fmt,		       coproc ? treg + 1 : treg,		       (int) BFD_RELOC_LO16, AT);	  if (p != NULL)	    p += 4;	  /* FIXME: How do we handle overflow here?  */	  offset_expr.X_add_number += 4;	  macro_build (p, &icnt, &offset_expr, s, fmt,		       coproc ? treg : treg + 1,		       (int) BFD_RELOC_LO16, AT);	}	        else if (mips_pic == SVR4_PIC)	{	  int off;	  /* If this is a reference to an external symbol, we want	       lw	$at,<sym>($gp)		(BFD_RELOC_MIPS_GOT16)	       nop	       <op>	$treg,0($at)	       <op>	$treg+1,4($at)	     Otherwise we want	       lw	$at,<sym>($gp)		(BFD_RELOC_MIPS_GOT16)	       nop	       <op>	$treg,<sym>($at)	(BFD_RELOC_LO16)	       <op>	$treg+1,<sym>+4($at)	(BFD_RELOC_LO16)	     If there is a base register we add it to $at before the	     lwc1 instructions.  If there is a constant we include it	     in the lwc1 instructions.  */	  used_at = 1;	  expr1.X_add_number = offset_expr.X_add_number;	  offset_expr.X_add_number = 0;	  if (expr1.X_add_number < -0x8000	      || expr1.X_add_number >= 0x8000 - 4)	    as_bad ("PIC code offset overflow (max 16 signed bits)");	  if (breg == 0)	    off = 0;	  else	    off = 4;	  frag_grow (24 + off);	  macro_build ((char *) NULL, &icnt, &offset_expr,		       mips_isa < 3 ? "lw" : "ld",		       "t,o(b)", AT, (int) BFD_RELOC_MIPS_GOT16, GP);	  macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "nop", "");	  if (breg != 0)	    macro_build ((char *) NULL, &icnt, (expressionS *) NULL,			 mips_isa < 3 ? "addu" : "daddu",			 "d,v,t", AT, breg, AT);	  macro_build ((char *) NULL, &icnt, &expr1, s, fmt,		       coproc ? treg + 1 : treg,		       (int) BFD_RELOC_LO16, AT);	  expr1.X_add_number += 4;	  /* Set mips_optimize to 2 to avoid inserting an undesired             nop.  */	  hold_mips_optimize = mips_optimize;	  mips_optimize = 2;	  macro_build ((char *) NULL, &icnt, &expr1, s, fmt,		       coproc ? treg : treg + 1,		       (int) BFD_RELOC_LO16, AT);	  mips_optimize = hold_mips_optimize;	  (void) frag_var (rs_machine_dependent, 0, 0,			   RELAX_ENCODE (0, 0, -16 - off, -8, 1, 0),			   offset_expr.X_add_symbol, (long) 0,			   (char *) NULL);	}      else if (mips_pic == EMBEDDED_PIC)	{	  /* If there is no base register, we use	       <op>	$treg,<sym>($gp)	(BFD_RELOC_MIPS_GPREL)	       <op>	$treg+1,<sym>+4($gp)	(BFD_RELOC_MIPS_GPREL)	     If we have a base register, we use	       addu	$at,$breg,$gp	       <op>	$treg,<sym>($at)	(BFD_RELOC_MIPS_GPREL)	       <op>	$treg+1,<sym>+4($at)	(BFD_RELOC_MIPS_GPREL)	     */	  if (breg == 0)	    {	      tempreg = GP;	      used_at = 0;	    }	  else	    {	      macro_build ((char *) NULL, &icnt, (expressionS *) NULL,			   mips_isa < 3 ? "addu" : "daddu",			   "d,v,t", AT, breg, GP);	      tempreg = AT;	      used_at = 1;	    }	  macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,		       coproc ? treg + 1 : treg,		       (int) BFD_RELOC_MIPS_GPREL, tempreg);	  offset_expr.X_add_number += 4;	  macro_build ((char *) NULL, &icnt, &offset_expr, s, fmt,		       coproc ? treg : treg + 1,		       (int) BFD_RELOC_MIPS_GPREL, tempreg);	}      else	abort ();      if (! used_at)	return;      break;    case M_LD_OB:      s = "lw";      goto sd_ob;    case M_SD_OB:      s = "sw";    sd_ob:      assert (mips_isa < 3);      macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg,		   (int) BFD_RELOC_LO16, breg);      offset_expr.X_add_number += 4;      macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg + 1,		   (int) BFD_RELOC_LO16, breg);      return;#ifdef LOSING_COMPILER    default:      macro2 (ip);      return;    }  if (mips_noat)    as_warn ("Macro used $at after \".set noat\"");}          static voidmacro2 (ip)     struct mips_cl_insn *ip;{  register int treg, sreg, dreg, breg;  int tempreg;  int mask;  int icnt = 0;  int used_at;  expressionS expr1;  const char *s;  const char *s2;  const char *fmt;  int likely = 0;  int dbl = 0;  int coproc = 0;  int lr = 0;  int off;  offsetT maxnum;  bfd_reloc_code_real_type r;  char *p;            treg = (ip->insn_opcode >> 16) & 0x1f;  dreg = (ip->insn_opcode >> 11) & 0x1f;  sreg = breg = (ip->insn_opcode >> 21) & 0x1f;  mask = ip->insn_mo->mask;            expr1.X_op = O_constant;  expr1.X_op_symbol = NULL;  expr1.X_add_symbol = NULL;  expr1.X_add_number = 1;            switch (mask)    {#endif /* LOSING_COMPILER */    case M_DMUL:      dbl = 1;    case M_MUL:      macro_build ((char *) NULL, &icnt, NULL,		   dbl ? "dmultu" : "multu",		   "s,t", sreg, treg);      macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg);      return;    case M_DMUL_I:      dbl = 1;    case M_MUL_I:      /* The MIPS assembler some times generates shifts and adds.  I'm	 not trying to be that fancy. GCC should do this for us	 anyway.  */      load_register (&icnt, AT, &imm_expr, dbl);      macro_build ((char *) NULL, &icnt, NULL,		   dbl ? "dmult" : "mult",		   "s,t", sreg, AT);      macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg);      break;    case M_DMULO:      dbl = 1;    case M_MULO:      mips_emit_delays ();      ++mips_noreorder;      mips_any_noreorder = 1;      macro_build ((char *) NULL, &icnt, NULL,		   dbl ? "dmult" : "mult",		   "s,t", sreg, treg);      macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg);      macro_build ((char *) NULL, &icnt, NULL,		   dbl ? "dsra32" : "sra",		   "d,w,<", dreg, dreg, 31);      macro_build ((char *) NULL, &icnt, NULL, "mfhi", "d", AT);      if (mips_trap)	macro_build ((char *) NULL, &icnt, NULL, "tne", "s,t", dreg, AT);      else	{	  expr1.X_add_number = 8;	  macro_build ((char *) NULL, &icnt, &expr1, "beq", "s,t,p", dreg, AT);	  macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);	  macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);	}      --mips_noreorder;      macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg);      break;    case M_DMULOU:      dbl = 1;    case M_MULOU:      mips_emit_delays ();      ++mips_noreorder;      mips_any_noreorder = 1;      macro_build ((char *) NULL, &icnt, NULL,		   dbl ? "dmultu" : "multu",		   "s,t", sreg, treg);      macro_build ((char *) NULL, &icnt, NULL, "mfhi", "d", AT);      macro_build ((char *) NULL, &icnt, NULL, "mflo", "d", dreg);      if (mips_trap)	macro_build ((char *) NULL, &icnt, NULL, "tne", "s,t", AT, 0);      else	{	  expr1.X_add_number = 8;	  macro_build ((char *) NULL, &icnt, &expr1, "beq", "s,t,p", AT, 0);	  macro_build ((char *) NULL, &icnt, NULL, "nop", "", 0);	  macro_build ((char *) NULL, &icnt, NULL, "break", "c", 6);	}      --mips_noreorder;      break;    case M_ROL:      macro_build ((char *) NULL, &icnt, NULL, "subu", "d,v,t", AT, 0, treg);      macro_build ((char *) NULL, &icnt, NULL, "srlv", "d,t,s", AT, sreg, AT);      macro_build ((char *) NULL, &icnt, NULL, "sllv", "d,t,s", dreg, sreg,		   treg);      macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);      break;    case M_ROL_I:      macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", AT, sreg,		   imm_expr.X_add_number & 0x1f);      macro_build ((char *) NULL, &icnt, NULL, "srl", "d,w,<", dreg, sreg,		   (0 - imm_expr.X_add_number) & 0x1f);      macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);      break;    case M_ROR:      macro_build ((char *) NULL, &icnt, NULL, "subu", "d,v,t", AT, 0, treg);      macro_build ((char *) NULL, &icnt, NULL, "sllv", "d,t,s", AT, sreg, AT);      macro_build ((char *) NULL, &icnt, NULL, "srlv", "d,t,s", dreg, sreg,		   treg);      macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);      break;    case M_ROR_I:      macro_build ((char *) NULL, &icnt, NULL, "srl", "d,w,<", AT, sreg,		   imm_expr.X_add_number & 0x1f);      macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", dreg, sreg,		   (0 - imm_expr.X_add_number) & 0x1f);      macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", dreg, dreg, AT);      break;    case M_S_DOB:      assert (mips_isa < 2);      /* Even on a big endian machine $fn comes before $fn+1.  We have	 to adjust when storing to memory.  */      macro_build ((char *) NULL, &icnt, &offset_expr, "swc1", "T,o(b)",		   byte_order == LITTLE_ENDIAN ? treg : treg + 1,		   (int) BFD_RELOC_LO16, breg);      offset_expr.X_add_number += 4;      macro_build ((char *) NULL, &icnt, &offset_expr, "swc1", "T,o(b)",		   byte_order == LITTLE_ENDIAN ? treg + 1 : treg,		   (int) BFD_RELOC_LO16, breg);      return;    case M_SEQ:      if (sreg == 0)	macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg,		     treg, (int) BFD_RELOC_LO16);      else if (treg == 0)	macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg,		     sreg, (int) BFD_RELOC_LO16);      else	{	  macro_build ((char *) NULL, &icnt, NULL, "xor", "d,v,t", dreg,		       sreg, treg);	  macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg,		       dreg, (int) BFD_RELOC_LO16);	}      return;    case M_SEQ_I:      if (imm_expr.X_add_number == 0)	{	  macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg,		       sreg, (int) BFD_RELOC_LO16);	  return;	}      if (sreg == 0)	{	  as_warn ("Instruction %s: result is always false",		   ip->insn_mo->name);	  macro_build ((char *) NULL, &icnt, NULL, "move", "d,s", dreg, 0);	  return;	}      if (imm_expr.X_add_number >= 0 && imm_expr.X_add_number < 0x10000)	{	  macro_build ((char *) NULL, &icnt, &imm_expr, "xori", "t,r,i", dreg,		       sreg, (int) BFD_RELOC_LO16);	  used_at = 0;	}      else if (imm_expr.X_add_number > -0x8000 && imm_expr.X_add_number < 0)	{	  imm_expr.X_add_number = -imm_expr.X_add_number;	  macro_build ((char *) NULL, &icnt, &imm_expr,		       mips_isa < 3 ? "addiu" : "daddiu",		       "t,r,j", dreg, sreg,		       (int) BFD_RELOC_LO16);	  used_at = 0;	}      else	{	  load_register (&icnt, AT, &imm_expr, 0);	  macro_build ((char *) NULL, &icnt, NULL, "xor", "d,v,t", dreg,		       sreg, AT);	  used_at = 1;	}      macro_build ((char *) NULL, &icnt, &expr1, "sltiu", "t,r,j", dreg, dreg,		   (int) BFD_RELOC_LO16);      if (used_at)	break;      return;    case M_SGE:		/* sreg >= treg <==> not (sreg < treg) */      s = "slt";      goto sge;    case M_SGEU:      s = "sltu";    sge:      macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, sreg, treg);      macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,		   (int) BFD_RELOC_LO16);      return;    case M_SGE_I:		/* sreg >= I <==> not (sreg < I) */    case M_SGEU_I:      if (imm_expr.X_add_number >= -0x8000 && imm_expr.X_add_number < 0x8000)	{	  macro_build ((char *) NULL, &icnt, &expr1,		       mask == M_SGE_I ? "slti" : "sltiu",		       "t,r,j", dreg, sreg, (int) BFD_RELOC_LO16);	  used_at = 0;	}      else	{	  load_register (&icnt, AT, &imm_expr, 0);	  macro_build ((char *) NULL, &icnt, NULL,		       mask == M_SGE_I ? "slt" : "sltu",		       "d,v,t", dreg, sreg, AT);	  used_at = 1;	}      macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,		   (int) BFD_RELOC_LO16);      if (used_at)	break;      return;    case M_SGT:		/* sreg > treg  <==>  treg < sreg */      s = "slt";      goto sgt;    case M_SGTU:      s = "sltu";    sgt:      macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, treg, sreg);      return;    case M_SGT_I:		/* sreg > I  <==>  I < sreg */      s = "slt";      goto sgti;    case M_SGTU_I:      s = "sltu";    sgti:      load_register (&icnt, AT, &imm_expr, 0);      macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, AT, sreg);      break;    case M_SLE:		/* sreg <= treg  <==>  treg >= sreg  <==>  not (treg < sreg) */      s = "slt";      goto sle;    case M_SLEU:      s = "sltu";    sle:      macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, treg, sreg);      macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,		   (int) BFD_RELOC_LO16);      return;    case M_SLE_I:		/* sreg <= I <==> I >= sreg <==> not (I < sreg) */      s = "slt";      goto slei;    case M_SLEU_I:      s = "sltu";    slei:      load_register (&icnt, AT, &imm_expr, 0);      macro_build ((char *) NULL, &icnt, NULL, s, "d,v,t", dreg, AT, sreg);      macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", dreg, dreg,		   (int) BFD_RELOC_LO16);      break;    case M_SLT_I:      if (imm_expr.X_add_number >= -0x8000 && imm_expr.X_add_number < 0x8000)	{	  macro_build ((char *) NULL, &icnt, &imm_expr, "slti", "t,r,j",		       dreg, sreg, (int) BFD_RELOC_LO16);	  return;	}      load_register (&icnt, AT, &imm_expr, 0);      macro_build ((char *) NULL, &icnt, NULL, "slt", "d,v,t", dreg, sreg, AT);      break;    case M_SLTU_I:      if (imm_expr.X_add_number >= -0x8000 && imm_expr.X_add_number < 0x8000)	{	  macro_build ((char *) NULL, &icnt, &imm_expr, "sltiu", "t,r,j",		       dreg, sreg, (int) BFD_RELOC_LO16);	  return;	}      load_register (&icnt, AT, &imm_expr, 0);      macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, sreg,		   AT);      break;    case M_SNE:      if (sreg == 0)	macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0,		     treg);      else if (treg == 0)	macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0,		     sreg);      else	{	  macro_build ((char *) NULL, &icnt, NULL, "xor", "d,v,t", dreg,		       sreg, treg);	  macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0,		       dreg);	}      return;    case M_SNE_I:      if (imm_expr.X_add_number == 0)	{	  macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0,		       sreg);	  return;	}      if (sreg == 0)	{	  as_warn ("Instruction %s: result is always true",		   ip->insn_mo->name);	  macro_build ((char *) NULL, &icnt, &expr1,		       mips_isa < 3 ? "addiu" : "daddiu",		       "t,r,j", dreg, 0, (int) BFD_RELOC_LO16);	  return;	}      if (imm_expr.X_add_number >= 0 && imm_expr.X_add_number < 0x10000)	{	  macro_build ((char *) NULL, &icnt, &imm_expr, "xori", "t,r,i",		       dreg, sreg, (int) BFD_RELOC_LO16);	  used_at = 0;	}      else if (imm_expr.X_add_number > -0x8000 && imm_expr.X_add_number < 0)	{	  imm_expr.X_add_number = -imm_expr.X_add_number;	  macro_build ((char *) NULL, &icnt, &imm_expr,		       mips_isa < 3 ? "addiu" : "daddiu",		       "t,r,j", dreg, sreg, (int) BFD_RELOC_LO16);	  used_at = 0;	}      else	{	  load_register (&icnt, AT, &imm_expr, 0);	  macro_build ((char *) NULL, &icnt, NULL, "xor", "d,v,t", dreg,		       sreg, AT);	  used_at = 1;	}      macro_build ((char *) NULL, &icnt, NULL, "sltu", "d,v,t", dreg, 0, dreg);      if (used_at)	break;      return;    case M_DSUB_I:      dbl = 1;    case M_SUB_I:      if (imm_expr.X_add_number > -0x8000 && imm_expr.X_add_number <= 0x8000)	{	  imm_expr.X_add_number = -imm_expr.X_add_number;	  macro_build ((char *) NULL, &icnt, &imm_expr,		       dbl ? "daddi" : "addi",		       "t,r,j", dreg, sreg, (int) BFD_RELOC_LO16);	  return;	}      load_register (&icnt, AT, &imm_expr, dbl);      macro_build ((char *) NULL, &icnt, NULL,		   dbl ? "dsub" : "sub",		   "d,v,t", dreg, sreg, AT);      break;    case M_DSUBU_I:      dbl = 1;    case M_SUBU_I:      if (imm_expr.X_add_number > -0x8000 && imm_expr.X_add_number <= 0x8000)	{	  imm_expr.X_add_number = -imm_expr.X_add_number;	  macro_build ((char *) NULL, &icnt, &imm_expr,		       dbl ? "daddiu" : "addiu",		       "t,r,j", dreg, sreg, (int) BFD_RELOC_LO16);	  return;	}      load_register (&icnt, AT, &imm_expr, dbl);      macro_build ((char *) NULL, &icnt, NULL,		   dbl ? "dsubu" : "subu",		   "d,v,t", dreg, sreg, AT);      break;    case M_TEQ_I:      s = "teq";      goto trap;    case M_TGE_I:      s = "tge";      goto trap;    case M_TGEU_I:      s = "tgeu";      goto trap;    case M_TLT_I:      s = "tlt";      goto trap;    case M_TLTU_I:      s = "tltu";      goto trap;    case M_TNE_I:      s = "tne";    trap:      load_register (&icnt, AT, &imm_expr, 0);      macro_build ((char *) NULL, &icnt, NULL, s, "s,t", sreg, AT);      break;    case M_TRUNCWD:    case M_TRUNCWS:      assert (mips_isa < 2);      sreg = (ip->insn_opcode >> 11) & 0x1f;	/* floating reg */      dreg = (ip->insn_opcode >> 06) & 0x1f;	/* floating reg */      /*       * Is the double cfc1 instruction a bug in the mips assembler;       * or is there a reason for it?       */      mips_emit_delays ();      ++mips_noreorder;      mips_any_noreorder = 1;      macro_build ((char *) NULL, &icnt, NULL, "cfc1", "t,G", treg, 31);      macro_build ((char *) NULL, &icnt, NULL, "cfc1", "t,G", treg, 31);      macro_build ((char *) NULL, &icnt, NULL, "nop", "");      expr1.X_add_number = 3;      macro_build ((char *) NULL, &icnt, &expr1, "ori", "t,r,i", AT, treg,		   (int) BFD_RELOC_LO16);      expr1.X_add_number = 2;      macro_build ((char *) NULL, &icnt, &expr1, "xori", "t,r,i", AT, AT,		     (int) BFD_RELOC_LO16);      macro_build ((char *) NULL, &icnt, NULL, "ctc1", "t,G", AT, 31);      macro_build ((char *) NULL, &icnt, NULL, "nop", "");      macro_build ((char *) NULL, &icnt, NULL,	      mask == M_TRUNCWD ? "cvt.w.d" : "cvt.w.s", "D,S", dreg, sreg);      macro_build ((char *) NULL, &icnt, NULL, "ctc1", "t,G", treg, 31);      macro_build ((char *) NULL, &icnt, NULL, "nop", "");      --mips_noreorder;      break;    case M_ULH:      s = "lb";      goto ulh;    case M_ULHU:      s = "lbu";    ulh:      if (offset_expr.X_add_number >= 0x7fff)	as_bad ("operand overflow");      /* avoid load delay */      if (byte_order == LITTLE_ENDIAN)	offset_expr.X_add_number += 1;      macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg,		   (int) BFD_RELOC_LO16, breg);      if (byte_order == LITTLE_ENDIAN)	offset_expr.X_add_number -= 1;      else	offset_expr.X_add_number += 1;      macro_build ((char *) NULL, &icnt, &offset_expr, "lbu", "t,o(b)", AT,		   (int) BFD_RELOC_LO16, breg);      macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", treg, treg, 8);      macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", treg, treg, AT);      break;    case M_ULD:      s = "ldl";      s2 = "ldr";      off = 7;      goto ulw;    case M_ULW:      s = "lwl";      s2 = "lwr";      off = 3;    ulw:      if (offset_expr.X_add_number >= 0x8000 - off)	as_bad ("operand overflow");      if (byte_order == LITTLE_ENDIAN)	offset_expr.X_add_number += off;      macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg,		   (int) BFD_RELOC_LO16, breg);      if (byte_order == LITTLE_ENDIAN)	offset_expr.X_add_number -= off;      else	offset_expr.X_add_number += off;      macro_build ((char *) NULL, &icnt, &offset_expr, s2, "t,o(b)", treg,		   (int) BFD_RELOC_LO16, breg);      return;    case M_ULD_A:      s = "ldl";      s2 = "ldr";      off = 7;      goto ulwa;    case M_ULW_A:      s = "lwl";      s2 = "lwr";      off = 3;    ulwa:      load_address (&icnt, AT, &offset_expr);      if (breg != 0)	macro_build ((char *) NULL, &icnt, (expressionS *) NULL,		     mips_isa < 3 ? "addu" : "daddu",		     "d,v,t", AT, AT, breg);      if (byte_order == LITTLE_ENDIAN)	expr1.X_add_number = off;      else	expr1.X_add_number = 0;      macro_build ((char *) NULL, &icnt, &expr1, s, "t,o(b)", treg,		   (int) BFD_RELOC_LO16, AT);      if (byte_order == LITTLE_ENDIAN)	expr1.X_add_number = 0;      else	expr1.X_add_number = off;      macro_build ((char *) NULL, &icnt, &expr1, s2, "t,o(b)", treg,		   (int) BFD_RELOC_LO16, AT);      break;    case M_ULH_A:    case M_ULHU_A:      load_address (&icnt, AT, &offset_expr);      if (breg != 0)	macro_build ((char *) NULL, &icnt, (expressionS *) NULL,		     mips_isa < 3 ? "addu" : "daddu",		     "d,v,t", AT, AT, breg);      if (byte_order == BIG_ENDIAN)	expr1.X_add_number = 0;      macro_build ((char *) NULL, &icnt, &expr1,		   mask == M_ULH_A ? "lb" : "lbu", "t,o(b)", treg,		   (int) BFD_RELOC_LO16, AT);      if (byte_order == BIG_ENDIAN)	expr1.X_add_number = 1;      else	expr1.X_add_number = 0;      macro_build ((char *) NULL, &icnt, &expr1, "lbu", "t,o(b)", AT,		   (int) BFD_RELOC_LO16, AT);      macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", treg,		   treg, 8);      macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", treg,		   treg, AT);      break;    case M_USH:      if (offset_expr.X_add_number >= 0x7fff)	as_bad ("operand overflow");      if (byte_order == BIG_ENDIAN)	offset_expr.X_add_number += 1;      macro_build ((char *) NULL, &icnt, &offset_expr, "sb", "t,o(b)", treg,		   (int) BFD_RELOC_LO16, breg);      macro_build ((char *) NULL, &icnt, NULL, "srl", "d,w,<", AT, treg, 8);      if (byte_order == BIG_ENDIAN)	offset_expr.X_add_number -= 1;      else	offset_expr.X_add_number += 1;      macro_build ((char *) NULL, &icnt, &offset_expr, "sb", "t,o(b)", AT,		   (int) BFD_RELOC_LO16, breg);      break;    case M_USD:      s = "sdl";      s2 = "sdr";      off = 7;      goto usw;    case M_USW:      s = "swl";      s2 = "swr";      off = 3;    usw:      if (offset_expr.X_add_number >= 0x8000 - off)	as_bad ("operand overflow");      if (byte_order == LITTLE_ENDIAN)	offset_expr.X_add_number += off;      macro_build ((char *) NULL, &icnt, &offset_expr, s, "t,o(b)", treg,		   (int) BFD_RELOC_LO16, breg);      if (byte_order == LITTLE_ENDIAN)	offset_expr.X_add_number -= off;      else	offset_expr.X_add_number += off;      macro_build ((char *) NULL, &icnt, &offset_expr, s2, "t,o(b)", treg,		   (int) BFD_RELOC_LO16, breg);      return;    case M_USD_A:      s = "sdl";      s2 = "sdr";      off = 7;      goto uswa;    case M_USW_A:      s = "swl";      s2 = "swr";      off = 3;    uswa:      load_address (&icnt, AT, &offset_expr);      if (breg != 0)	macro_build ((char *) NULL, &icnt, (expressionS *) NULL,		     mips_isa < 3 ? "addu" : "daddu",		     "d,v,t", AT, AT, breg);      if (byte_order == LITTLE_ENDIAN)	expr1.X_add_number = off;      else	expr1.X_add_number = 0;      macro_build ((char *) NULL, &icnt, &expr1, s, "t,o(b)", treg,		   (int) BFD_RELOC_LO16, AT);      if (byte_order == LITTLE_ENDIAN)	expr1.X_add_number = 0;      else	expr1.X_add_number = off;      macro_build ((char *) NULL, &icnt, &expr1, s2, "t,o(b)", treg,		   (int) BFD_RELOC_LO16, AT);      break;    case M_USH_A:      load_address (&icnt, AT, &offset_expr);      if (breg != 0)	macro_build ((char *) NULL, &icnt, (expressionS *) NULL,		     mips_isa < 3 ? "addu" : "daddu",		     "d,v,t", AT, AT, breg);      if (byte_order == LITTLE_ENDIAN)	expr1.X_add_number = 0;      macro_build ((char *) NULL, &icnt, &expr1, "sb", "t,o(b)", treg,		   (int) BFD_RELOC_LO16, AT);      macro_build ((char *) NULL, &icnt, NULL, "srl", "d,w,<", treg,		   treg, 8);      if (byte_order == LITTLE_ENDIAN)	expr1.X_add_number = 1;      else	expr1.X_add_number = 0;      macro_build ((char *) NULL, &icnt, &expr1, "sb", "t,o(b)", treg,		   (int) BFD_RELOC_LO16, AT);      if (byte_order == LITTLE_ENDIAN)	expr1.X_add_number = 0;      else	expr1.X_add_number = 1;      macro_build ((char *) NULL, &icnt, &expr1, "lbu", "t,o(b)", AT,		   (int) BFD_RELOC_LO16, AT);      macro_build ((char *) NULL, &icnt, NULL, "sll", "d,w,<", treg,		   treg, 8);      macro_build ((char *) NULL, &icnt, NULL, "or", "d,v,t", treg,		   treg, AT);      break;    default:      as_bad ("Macro %s not implemented yet", ip->insn_mo->name);      break;    }  if (mips_noat)    as_warn ("Macro used $at after \".set noat\"");}