- case M_LBUE_AB:
- s = "lbue";
- fmt = "t,+j(b)";
- offbits = 9;
- goto ld_st;
- case M_LHUE_AB:
- s = "lhue";
- fmt = "t,+j(b)";
- offbits = 9;
- goto ld_st;
- case M_LBE_AB:
- s = "lbe";
- fmt = "t,+j(b)";
- offbits = 9;
- goto ld_st;
- case M_LHE_AB:
- s = "lhe";
- fmt = "t,+j(b)";
- offbits = 9;
- goto ld_st;
- case M_LLE_AB:
- s = "lle";
- fmt = "t,+j(b)";
- offbits = 9;
- goto ld_st;
- case M_LWE_AB:
- s = "lwe";
- fmt = "t,+j(b)";
- offbits = 9;
- goto ld_st;
- case M_LWLE_AB:
- s = "lwle";
- fmt = "t,+j(b)";
- offbits = 9;
- goto ld_st;
- case M_LWRE_AB:
- s = "lwre";
- fmt = "t,+j(b)";
- offbits = 9;
- goto ld_st;
- case M_SBE_AB:
- s = "sbe";
- fmt = "t,+j(b)";
- offbits = 9;
- goto ld_st;
- case M_SCE_AB:
- s = "sce";
- fmt = "t,+j(b)";
- offbits = 9;
- goto ld_st;
- case M_SHE_AB:
- s = "she";
- fmt = "t,+j(b)";
- offbits = 9;
- goto ld_st;
- case M_SWE_AB:
- s = "swe";
- fmt = "t,+j(b)";
- offbits = 9;
- goto ld_st;
- case M_SWLE_AB:
- s = "swle";
- fmt = "t,+j(b)";
- offbits = 9;
- goto ld_st;
- case M_SWRE_AB:
- s = "swre";
- fmt = "t,+j(b)";
- offbits = 9;
- goto ld_st;
- case M_ACLR_AB:
- s = "aclr";
- treg = EXTRACT_OPERAND (mips_opts.micromips, 3BITPOS, *ip);
- fmt = "\\,~(b)";
- offbits = 12;
- goto ld_st;
- case M_ASET_AB:
- s = "aset";
- treg = EXTRACT_OPERAND (mips_opts.micromips, 3BITPOS, *ip);
- fmt = "\\,~(b)";
- offbits = 12;
- goto ld_st;
- case M_LB_AB:
- s = "lb";
- fmt = "t,o(b)";
- goto ld;
- case M_LBU_AB:
- s = "lbu";
- fmt = "t,o(b)";
- goto ld;
- case M_LH_AB:
- s = "lh";
- fmt = "t,o(b)";
- goto ld;
- case M_LHU_AB:
- s = "lhu";
- fmt = "t,o(b)";
- goto ld;
- case M_LW_AB:
- s = "lw";
- fmt = "t,o(b)";
- goto ld;
- case M_LWC0_AB:
- gas_assert (!mips_opts.micromips);
- s = "lwc0";
- fmt = "E,o(b)";
- /* Itbl support may require additional care here. */
- coproc = 1;
- goto ld_st;
- case M_LWC1_AB:
- s = "lwc1";
- fmt = "T,o(b)";
- /* Itbl support may require additional care here. */
- coproc = 1;
- goto ld_st;
- case M_LWC2_AB:
- s = "lwc2";
- fmt = COP12_FMT;
- offbits = (mips_opts.micromips ? 12 : 16);
- /* Itbl support may require additional care here. */
- coproc = 1;
- goto ld_st;
- case M_LWC3_AB:
- gas_assert (!mips_opts.micromips);
- s = "lwc3";
- fmt = "E,o(b)";
- /* Itbl support may require additional care here. */
- coproc = 1;
- goto ld_st;
- case M_LWL_AB:
- s = "lwl";
- fmt = MEM12_FMT;
- offbits = (mips_opts.micromips ? 12 : 16);
- goto ld_st;
- case M_LWR_AB:
- s = "lwr";
- fmt = MEM12_FMT;
- offbits = (mips_opts.micromips ? 12 : 16);
- goto ld_st;
- case M_LDC1_AB:
- s = "ldc1";
- fmt = "T,o(b)";
- /* Itbl support may require additional care here. */
- coproc = 1;
- goto ld_st;
- case M_LDC2_AB:
- s = "ldc2";
- fmt = COP12_FMT;
- offbits = (mips_opts.micromips ? 12 : 16);
- /* Itbl support may require additional care here. */
- coproc = 1;
- goto ld_st;
- case M_LQC2_AB:
- s = "lqc2";
- fmt = "E,o(b)";
- /* Itbl support may require additional care here. */
- coproc = 1;
- goto ld_st;
- case M_LDC3_AB:
- s = "ldc3";
- fmt = "E,o(b)";
- /* Itbl support may require additional care here. */
- coproc = 1;
- goto ld_st;
- case M_LDL_AB:
- s = "ldl";
- fmt = MEM12_FMT;
- offbits = (mips_opts.micromips ? 12 : 16);
- goto ld_st;
- case M_LDR_AB:
- s = "ldr";
- fmt = MEM12_FMT;
- offbits = (mips_opts.micromips ? 12 : 16);
- goto ld_st;
- case M_LL_AB:
- s = "ll";
- fmt = MEM12_FMT;
- offbits = (mips_opts.micromips ? 12 : 16);
- goto ld;
- case M_LLD_AB:
- s = "lld";
- fmt = MEM12_FMT;
- offbits = (mips_opts.micromips ? 12 : 16);
- goto ld;
- case M_LWU_AB:
- s = "lwu";
- fmt = MEM12_FMT;
- offbits = (mips_opts.micromips ? 12 : 16);
- goto ld;
- case M_LWP_AB:
- gas_assert (mips_opts.micromips);
- s = "lwp";
- fmt = "t,~(b)";
- offbits = 12;
- lp = 1;
- goto ld;
- case M_LDP_AB:
- gas_assert (mips_opts.micromips);
- s = "ldp";
- fmt = "t,~(b)";
- offbits = 12;
- lp = 1;
- goto ld;
- case M_LWM_AB:
- gas_assert (mips_opts.micromips);
- s = "lwm";
- fmt = "n,~(b)";
- offbits = 12;
- goto ld_st;
- case M_LDM_AB:
- gas_assert (mips_opts.micromips);
- s = "ldm";
- fmt = "n,~(b)";
- offbits = 12;
- goto ld_st;
-
- ld:
- /* We don't want to use $0 as tempreg. */
- if (breg == treg + lp || treg + lp == ZERO)
- goto ld_st;
- else
- tempreg = treg + lp;
- goto ld_noat;
-
- case M_SB_AB:
- s = "sb";
- fmt = "t,o(b)";
- goto ld_st;
- case M_SH_AB:
- s = "sh";
- fmt = "t,o(b)";
- goto ld_st;
- case M_SW_AB:
- s = "sw";
- fmt = "t,o(b)";
- goto ld_st;
- case M_SWC0_AB:
- gas_assert (!mips_opts.micromips);
- s = "swc0";
- fmt = "E,o(b)";
- /* Itbl support may require additional care here. */
- coproc = 1;
- goto ld_st;
- case M_SWC1_AB:
- s = "swc1";
- fmt = "T,o(b)";
- /* Itbl support may require additional care here. */
- coproc = 1;
- goto ld_st;
- case M_SWC2_AB:
- s = "swc2";
- fmt = COP12_FMT;
- offbits = (mips_opts.micromips ? 12 : 16);
- /* Itbl support may require additional care here. */
- coproc = 1;
- goto ld_st;
- case M_SWC3_AB:
- gas_assert (!mips_opts.micromips);
- s = "swc3";
- fmt = "E,o(b)";
- /* Itbl support may require additional care here. */
- coproc = 1;
- goto ld_st;
- case M_SWL_AB:
- s = "swl";
- fmt = MEM12_FMT;
- offbits = (mips_opts.micromips ? 12 : 16);
- goto ld_st;
- case M_SWR_AB:
- s = "swr";
- fmt = MEM12_FMT;
- offbits = (mips_opts.micromips ? 12 : 16);
- goto ld_st;
- case M_SC_AB:
- s = "sc";
- fmt = MEM12_FMT;
- offbits = (mips_opts.micromips ? 12 : 16);
- goto ld_st;
- case M_SCD_AB:
- s = "scd";
- fmt = MEM12_FMT;
- offbits = (mips_opts.micromips ? 12 : 16);
- goto ld_st;
- case M_CACHE_AB:
- s = "cache";
- fmt = mips_opts.micromips ? "k,~(b)" : "k,o(b)";
- offbits = (mips_opts.micromips ? 12 : 16);
- goto ld_st;
- case M_CACHEE_AB:
- s = "cachee";
- fmt = "k,+j(b)";
- offbits = 9;
- goto ld_st;
- case M_PREF_AB:
- s = "pref";
- fmt = !mips_opts.micromips ? "k,o(b)" : "k,~(b)";
- offbits = (mips_opts.micromips ? 12 : 16);
- goto ld_st;
- case M_PREFE_AB:
- s = "prefe";
- fmt = "k,+j(b)";
- offbits = 9;
- goto ld_st;
- case M_SDC1_AB:
- s = "sdc1";
- fmt = "T,o(b)";
- coproc = 1;
- /* Itbl support may require additional care here. */
- goto ld_st;
- case M_SDC2_AB:
- s = "sdc2";
- fmt = COP12_FMT;
- offbits = (mips_opts.micromips ? 12 : 16);
- /* Itbl support may require additional care here. */
- coproc = 1;
- goto ld_st;
- case M_SQC2_AB:
- s = "sqc2";
- fmt = "E,o(b)";
- /* Itbl support may require additional care here. */
- coproc = 1;
- goto ld_st;
- case M_SDC3_AB:
- gas_assert (!mips_opts.micromips);
- s = "sdc3";
- fmt = "E,o(b)";
- /* Itbl support may require additional care here. */
- coproc = 1;
- goto ld_st;
- case M_SDL_AB:
- s = "sdl";
- fmt = MEM12_FMT;
- offbits = (mips_opts.micromips ? 12 : 16);
- goto ld_st;
- case M_SDR_AB:
- s = "sdr";
- fmt = MEM12_FMT;
- offbits = (mips_opts.micromips ? 12 : 16);
- goto ld_st;
- case M_SWP_AB:
- gas_assert (mips_opts.micromips);
- s = "swp";
- fmt = "t,~(b)";
- offbits = 12;
- goto ld_st;
- case M_SDP_AB:
- gas_assert (mips_opts.micromips);
- s = "sdp";
- fmt = "t,~(b)";
- offbits = 12;
- goto ld_st;
- case M_SWM_AB:
- gas_assert (mips_opts.micromips);
- s = "swm";
- fmt = "n,~(b)";
- offbits = 12;
- goto ld_st;
- case M_SDM_AB:
- gas_assert (mips_opts.micromips);
- s = "sdm";
- fmt = "n,~(b)";
- offbits = 12;
-
- ld_st:
- tempreg = AT;
- ld_noat:
- if (small_offset_p (0, align, 16))
- {
- /* The first case exists for M_LD_AB and M_SD_AB, which are
- macros for o32 but which should act like normal instructions
- otherwise. */
- if (offbits == 16)
- macro_build (&offset_expr, s, fmt, treg, -1, offset_reloc[0],
- offset_reloc[1], offset_reloc[2], breg);
- else if (small_offset_p (0, align, offbits))
- {
- if (offbits == 0)
- macro_build (NULL, s, fmt, treg, breg);
- else
- macro_build (NULL, s, fmt, treg,
- (int) offset_expr.X_add_number, breg);
- }
- else
- {
- if (tempreg == AT)
- used_at = 1;
- macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j",
- tempreg, breg, -1, offset_reloc[0],
- offset_reloc[1], offset_reloc[2]);
- if (offbits == 0)
- macro_build (NULL, s, fmt, treg, tempreg);
- else
- macro_build (NULL, s, fmt, treg, 0, tempreg);
- }
- break;
- }
-
- if (tempreg == AT)
- used_at = 1;
-
- if (offset_expr.X_op != O_constant
- && offset_expr.X_op != O_symbol)
- {
- as_bad (_("Expression too complex"));
- offset_expr.X_op = O_constant;
- }
-
- if (HAVE_32BIT_ADDRESSES
- && !IS_SEXT_32BIT_NUM (offset_expr.X_add_number))
- {
- char value [32];
-
- sprintf_vma (value, offset_expr.X_add_number);
- as_bad (_("Number (0x%s) larger than 32 bits"), value);
- }
-
- /* A constant expression in PIC code can be handled just as it
- is in non PIC code. */
- if (offset_expr.X_op == O_constant)
- {
- expr1.X_add_number = offset_high_part (offset_expr.X_add_number,
- offbits == 0 ? 16 : offbits);
- offset_expr.X_add_number -= expr1.X_add_number;
-
- load_register (tempreg, &expr1, HAVE_64BIT_ADDRESSES);
- if (breg != 0)
- macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- tempreg, tempreg, breg);
- if (offbits == 0)
- {
- if (offset_expr.X_add_number != 0)
- macro_build (&offset_expr, ADDRESS_ADDI_INSN,
- "t,r,j", tempreg, tempreg, BFD_RELOC_LO16);
- macro_build (NULL, s, fmt, treg, tempreg);
- }
- else if (offbits == 16)
- macro_build (&offset_expr, s, fmt, treg, BFD_RELOC_LO16, tempreg);
- else
- macro_build (NULL, s, fmt, treg,
- (int) offset_expr.X_add_number, tempreg);
- }
- else if (offbits != 16)
- {
- /* The offset field is too narrow to be used for a low-part
- relocation, so load the whole address into the auxillary
- register. */
- load_address (tempreg, &offset_expr, &used_at);
- if (breg != 0)
- macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- tempreg, tempreg, breg);
- if (offbits == 0)
- macro_build (NULL, s, fmt, treg, tempreg);
- else
- macro_build (NULL, s, fmt, treg, 0, tempreg);
- }
- else if (mips_pic == NO_PIC)
- {
- /* If this is a reference to a GP relative symbol, and there
- is no base register, we want
- <op> $treg,<sym>($gp) (BFD_RELOC_GPREL16)
- 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_GPREL16)
- 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.
-
- With 64bit address space and no base register and $at usable,
- we want
- lui $tempreg,<sym> (BFD_RELOC_MIPS_HIGHEST)
- lui $at,<sym> (BFD_RELOC_HI16_S)
- daddiu $tempreg,<sym> (BFD_RELOC_MIPS_HIGHER)
- dsll32 $tempreg,0
- daddu $tempreg,$at
- <op> $treg,<sym>($tempreg) (BFD_RELOC_LO16)
- If we have a base register, we want
- lui $tempreg,<sym> (BFD_RELOC_MIPS_HIGHEST)
- lui $at,<sym> (BFD_RELOC_HI16_S)
- daddiu $tempreg,<sym> (BFD_RELOC_MIPS_HIGHER)
- daddu $at,$breg
- dsll32 $tempreg,0
- daddu $tempreg,$at
- <op> $treg,<sym>($tempreg) (BFD_RELOC_LO16)
-
- Without $at we can't generate the optimal path for superscalar
- processors here since this would require two temporary registers.
- lui $tempreg,<sym> (BFD_RELOC_MIPS_HIGHEST)
- daddiu $tempreg,<sym> (BFD_RELOC_MIPS_HIGHER)
- dsll $tempreg,16
- daddiu $tempreg,<sym> (BFD_RELOC_HI16_S)
- dsll $tempreg,16
- <op> $treg,<sym>($tempreg) (BFD_RELOC_LO16)
- If we have a base register, we want
- lui $tempreg,<sym> (BFD_RELOC_MIPS_HIGHEST)
- daddiu $tempreg,<sym> (BFD_RELOC_MIPS_HIGHER)
- dsll $tempreg,16
- daddiu $tempreg,<sym> (BFD_RELOC_HI16_S)
- dsll $tempreg,16
- daddu $tempreg,$tempreg,$breg
- <op> $treg,<sym>($tempreg) (BFD_RELOC_LO16)
-
- For GP relative symbols in 64bit address space we can use
- the same sequence as in 32bit address space. */
- if (HAVE_64BIT_SYMBOLS)
- {
- if ((valueT) offset_expr.X_add_number <= MAX_GPREL_OFFSET
- && !nopic_need_relax (offset_expr.X_add_symbol, 1))
- {
- relax_start (offset_expr.X_add_symbol);
- if (breg == 0)
- {
- macro_build (&offset_expr, s, fmt, treg,
- BFD_RELOC_GPREL16, mips_gp_register);
- }
- else
- {
- macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- tempreg, breg, mips_gp_register);
- macro_build (&offset_expr, s, fmt, treg,
- BFD_RELOC_GPREL16, tempreg);
- }
- relax_switch ();
- }
-
- if (used_at == 0 && mips_opts.at)
- {
- macro_build (&offset_expr, "lui", LUI_FMT, tempreg,
- BFD_RELOC_MIPS_HIGHEST);
- macro_build (&offset_expr, "lui", LUI_FMT, AT,
- BFD_RELOC_HI16_S);
- macro_build (&offset_expr, "daddiu", "t,r,j", tempreg,
- tempreg, BFD_RELOC_MIPS_HIGHER);
- if (breg != 0)
- macro_build (NULL, "daddu", "d,v,t", AT, AT, breg);
- macro_build (NULL, "dsll32", SHFT_FMT, tempreg, tempreg, 0);
- macro_build (NULL, "daddu", "d,v,t", tempreg, tempreg, AT);
- macro_build (&offset_expr, s, fmt, treg, BFD_RELOC_LO16,
- tempreg);
- used_at = 1;
- }
- else
- {
- macro_build (&offset_expr, "lui", LUI_FMT, tempreg,
- BFD_RELOC_MIPS_HIGHEST);
- macro_build (&offset_expr, "daddiu", "t,r,j", tempreg,
- tempreg, BFD_RELOC_MIPS_HIGHER);
- macro_build (NULL, "dsll", SHFT_FMT, tempreg, tempreg, 16);
- macro_build (&offset_expr, "daddiu", "t,r,j", tempreg,
- tempreg, BFD_RELOC_HI16_S);
- macro_build (NULL, "dsll", SHFT_FMT, tempreg, tempreg, 16);
- if (breg != 0)
- macro_build (NULL, "daddu", "d,v,t",
- tempreg, tempreg, breg);
- macro_build (&offset_expr, s, fmt, treg,
- BFD_RELOC_LO16, tempreg);
- }
-
- if (mips_relax.sequence)
- relax_end ();
- break;
- }
-
- if (breg == 0)
- {
- if ((valueT) offset_expr.X_add_number <= MAX_GPREL_OFFSET
- && !nopic_need_relax (offset_expr.X_add_symbol, 1))
- {
- relax_start (offset_expr.X_add_symbol);
- macro_build (&offset_expr, s, fmt, treg, BFD_RELOC_GPREL16,
- mips_gp_register);
- relax_switch ();
- }
- macro_build_lui (&offset_expr, tempreg);
- macro_build (&offset_expr, s, fmt, treg,
- BFD_RELOC_LO16, tempreg);
- if (mips_relax.sequence)
- relax_end ();
- }
- else
- {
- if ((valueT) offset_expr.X_add_number <= MAX_GPREL_OFFSET
- && !nopic_need_relax (offset_expr.X_add_symbol, 1))
- {
- relax_start (offset_expr.X_add_symbol);
- macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- tempreg, breg, mips_gp_register);
- macro_build (&offset_expr, s, fmt, treg,
- BFD_RELOC_GPREL16, tempreg);
- relax_switch ();
- }
- macro_build_lui (&offset_expr, tempreg);
- macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- tempreg, tempreg, breg);
- macro_build (&offset_expr, s, fmt, treg,
- BFD_RELOC_LO16, tempreg);
- if (mips_relax.sequence)
- relax_end ();
- }
- }
- else if (!mips_big_got)
- {
- int lw_reloc_type = (int) BFD_RELOC_MIPS_GOT16;
-
- /* 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)
-
- For NewABI, we want
- lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT_PAGE)
- <op> $treg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_OFST)
-
- 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). */
- gas_assert (offset_expr.X_op == O_symbol);
- if (HAVE_NEWABI)
- {
- macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
- BFD_RELOC_MIPS_GOT_PAGE, mips_gp_register);
- if (breg != 0)
- macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- tempreg, tempreg, breg);
- macro_build (&offset_expr, s, fmt, treg,
- BFD_RELOC_MIPS_GOT_OFST, tempreg);
- break;
- }
- 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)"));
- macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
- lw_reloc_type, mips_gp_register);
- load_delay_nop ();
- relax_start (offset_expr.X_add_symbol);
- relax_switch ();
- macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", tempreg,
- tempreg, BFD_RELOC_LO16);
- relax_end ();
- if (breg != 0)
- macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- tempreg, tempreg, breg);
- macro_build (&expr1, s, fmt, treg, BFD_RELOC_LO16, tempreg);
- }
- else if (mips_big_got && !HAVE_NEWABI)
- {
- int gpdelay;
-
- /* If this is a reference to an external symbol, we want
- lui $tempreg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
- addu $tempreg,$tempreg,$gp
- lw $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_LO16)
- <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). */
- gas_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)"));
- gpdelay = reg_needs_delay (mips_gp_register);
- relax_start (offset_expr.X_add_symbol);
- macro_build (&offset_expr, "lui", LUI_FMT, tempreg,
- BFD_RELOC_MIPS_GOT_HI16);
- macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", tempreg, tempreg,
- mips_gp_register);
- macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
- BFD_RELOC_MIPS_GOT_LO16, tempreg);
- relax_switch ();
- if (gpdelay)
- macro_build (NULL, "nop", "");
- macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
- BFD_RELOC_MIPS_GOT16, mips_gp_register);
- load_delay_nop ();
- macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", tempreg,
- tempreg, BFD_RELOC_LO16);
- relax_end ();
-
- if (breg != 0)
- macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- tempreg, tempreg, breg);
- macro_build (&expr1, s, fmt, treg, BFD_RELOC_LO16, tempreg);
- }
- else if (mips_big_got && HAVE_NEWABI)
- {
- /* If this is a reference to an external symbol, we want
- lui $tempreg,<sym> (BFD_RELOC_MIPS_GOT_HI16)
- add $tempreg,$tempreg,$gp
- lw $tempreg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_LO16)
- <op> $treg,<ofst>($tempreg)
- Otherwise, for local symbols, we want:
- lw $tempreg,<sym>($gp) (BFD_RELOC_MIPS_GOT_PAGE)
- <op> $treg,<sym>($tempreg) (BFD_RELOC_MIPS_GOT_OFST) */
- gas_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)"));
- relax_start (offset_expr.X_add_symbol);
- macro_build (&offset_expr, "lui", LUI_FMT, tempreg,
- BFD_RELOC_MIPS_GOT_HI16);
- macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", tempreg, tempreg,
- mips_gp_register);
- macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
- BFD_RELOC_MIPS_GOT_LO16, tempreg);
- if (breg != 0)
- macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- tempreg, tempreg, breg);
- macro_build (&expr1, s, fmt, treg, BFD_RELOC_LO16, tempreg);
-
- relax_switch ();
- offset_expr.X_add_number = expr1.X_add_number;
- macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", tempreg,
- BFD_RELOC_MIPS_GOT_PAGE, mips_gp_register);
- if (breg != 0)
- macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- tempreg, tempreg, breg);
- macro_build (&offset_expr, s, fmt, treg,
- BFD_RELOC_MIPS_GOT_OFST, tempreg);
- relax_end ();
- }
- else
- abort ();
-
- break;
-
- case M_JRADDIUSP:
- gas_assert (mips_opts.micromips);
- gas_assert (mips_opts.insn32);
- start_noreorder ();
- macro_build (NULL, "jr", "s", RA);
- expr1.X_add_number = EXTRACT_OPERAND (1, IMMP, *ip) << 2;
- macro_build (&expr1, "addiu", "t,r,j", SP, SP, BFD_RELOC_LO16);
- end_noreorder ();
- break;
-
- case M_JRC:
- gas_assert (mips_opts.micromips);
- gas_assert (mips_opts.insn32);
- macro_build (NULL, "jr", "s", sreg);
- if (mips_opts.noreorder)
- macro_build (NULL, "nop", "");
- break;
-
- case M_LI:
- case M_LI_S:
- load_register (treg, &imm_expr, 0);
- break;
-
- case M_DLI:
- load_register (treg, &imm_expr, 1);
- break;
-
- case M_LI_SS:
- if (imm_expr.X_op == O_constant)