+ if (expr1.X_add_number == 0)
+ {
+ p = frag_var (rs_machine_dependent, 8, 0,
+ RELAX_ENCODE (12, 8, 0, 4, 0,
+ mips_opts.warn_about_macros),
+ offset_expr.X_add_symbol, 0, NULL);
+ }
+ else if (expr1.X_add_number >= -0x8000
+ && expr1.X_add_number < 0x8000)
+ {
+ macro_build (NULL, &icnt, &expr1, ADDRESS_ADDI_INSN, "t,r,j",
+ tempreg, tempreg, BFD_RELOC_LO16);
+ p = frag_var (rs_machine_dependent, 8, 0,
+ RELAX_ENCODE (16, 8, 0, 4, 0,
+ mips_opts.warn_about_macros),
+ offset_expr.X_add_symbol, 0, NULL);
+ }
+ else if (IS_SEXT_32BIT_NUM (expr1.X_add_number))
+ {
+ int dreg;
+
+ /* 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)
+ dreg = tempreg;
+ else
+ {
+ assert (tempreg == AT);
+ macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ treg, AT, breg);
+ dreg = treg;
+ adj = 4;
+ }
+
+ /* Set mips_optimize around the lui instruction to avoid
+ inserting an unnecessary nop after the lw. */
+ macro_build_lui (NULL, &icnt, &expr1, AT);
+ macro_build (NULL, &icnt, &expr1, ADDRESS_ADDI_INSN,
+ "t,r,j", AT, AT, BFD_RELOC_LO16);
+ macro_build (NULL, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ dreg, dreg, AT);
+
+ p = frag_var (rs_machine_dependent, 8 + adj, 0,
+ RELAX_ENCODE (24 + adj, 8 + adj,
+ 0, 4, 0,
+ (breg == 0
+ ? mips_opts.warn_about_macros
+ : 0)),
+ offset_expr.X_add_symbol, 0, NULL);
+
+ used_at = 1;
+ }
+ else
+ as_bad (_("PIC code offset overflow (max 32 signed bits)"));
+
+ offset_expr.X_add_number = expr1.X_add_number;
+ macro_build (p, &icnt, &offset_expr, ADDRESS_LOAD_INSN, "t,o(b)",
+ tempreg, BFD_RELOC_MIPS_GOT_PAGE, mips_gp_register);
+ macro_build (p + 4, &icnt, &offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
+ tempreg, tempreg, BFD_RELOC_MIPS_GOT_OFST);
+ if (adj)
+ {
+ macro_build (p + 8, &icnt, NULL, ADDRESS_ADD_INSN, "d,v,t",
+ treg, tempreg, breg);
+ breg = 0;
+ tempreg = treg;
+ }
+ }
+ else if (mips_pic == EMBEDDED_PIC)
+ {
+ /* We use
+ addiu $tempreg,$gp,<sym> (BFD_RELOC_GPREL16)
+ */
+ macro_build (NULL, &icnt, &offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
+ tempreg, mips_gp_register, BFD_RELOC_GPREL16);
+ }
+ else
+ abort ();
+
+ if (breg != 0)
+ {
+ char *s;
+
+ if (mips_pic == EMBEDDED_PIC || mips_pic == NO_PIC)
+ s = (dbl || HAVE_64BIT_ADDRESSES) ? "daddu" : "addu";
+ else
+ s = ADDRESS_ADD_INSN;
+
+ macro_build (NULL, &icnt, NULL, s, "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 (NULL, &icnt, &offset_expr, "j", "a");
+ else
+ macro_build (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 (NULL, &icnt, 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 (NULL, &icnt, NULL, "jalr", "d,s", dreg, sreg);
+ if (! HAVE_NEWABI)