* config/tc-mips.c (mips_cpreturn_offset): New variable.

(mips_cpreturn_register): Likewise.
	(mips_gp_register): Likewise.
	(s_cpsetup): New function prototype.
	(s_cplocal): Likewise.
	(s_cpreturn): Likewise.
	(s_gpvalue): Likewise.
	(mips_pseudo_table): Add .cpsetup, .cplocal, .cpreturn, .gpvalue
	pseudo-ops.
	(macro): Don't warn about .cprestore for NewABI.
	(md_pcrel_from): Code cleanup.
	(mips_force_relocation): Force output of some NewABI relocations even
	without a defined symbol.
	(s_cpload): Ignore .cpload for NewABI.
	(s_cpsetup): Handle .cpsetup.
	(s_cplocal): Handle .cplocal.
	(s_cprestore): Ignore .cprestore for NewABI.
	(s_cpreturn): Handle .cpreturn.
	(s_gpvalue): Handle .gpvalue.
	(s_cpadd): Ignore .cpadd for NewABI.
	(nopic_need_relax): Take g_switch_value into account as gp
	optimization.
	(tc_gen_reloc): Don't handle BFD_RELOC_MIPS_{CALL,GOT}* for NewABI.
This commit is contained in:
Thiemo Seufer 2001-10-10 01:08:35 +00:00
parent ad8d3bb3cf
commit 6478892d2e
2 changed files with 258 additions and 33 deletions

View file

@ -1,3 +1,29 @@
2001-10-10 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
* config/tc-mips.c (mips_cpreturn_offset): New variable.
(mips_cpreturn_register): Likewise.
(mips_gp_register): Likewise.
(s_cpsetup): New function prototype.
(s_cplocal): Likewise.
(s_cpreturn): Likewise.
(s_gpvalue): Likewise.
(mips_pseudo_table): Add .cpsetup, .cplocal, .cpreturn, .gpvalue
pseudo-ops.
(macro): Don't warn about .cprestore for NewABI.
(md_pcrel_from): Code cleanup.
(mips_force_relocation): Force output of some NewABI relocations even
without a defined symbol.
(s_cpload): Ignore .cpload for NewABI.
(s_cpsetup): Handle .cpsetup.
(s_cplocal): Handle .cplocal.
(s_cprestore): Ignore .cprestore for NewABI.
(s_cpreturn): Handle .cpreturn.
(s_gpvalue): Handle .gpvalue.
(s_cpadd): Ignore .cpadd for NewABI.
(nopic_need_relax): Take g_switch_value into account as gp
optimization.
(tc_gen_reloc): Don't handle BFD_RELOC_MIPS_{CALL,GOT}* for NewABI.
2001-10-10 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
* config/tc-mips.c (my_getSmallParser): New function prototype.

View file

@ -393,6 +393,13 @@ static int auto_align = 1;
variable. */
static offsetT mips_cprestore_offset = -1;
/* Similiar for NewABI PIC code, where $gp is callee-saved. NewABI has some
more optimizations, it can use a register value instead of a memory-saved
offset and even an other than GP as global pointer. */
static offsetT mips_cpreturn_offset = -1;
static int mips_cpreturn_register = -1;
static int mips_gp_register = GP;
/* This is the register which holds the stack frame, as set by the
.frame pseudo-op. This is needed to implement .cprestore. */
static int mips_frame_reg = SP;
@ -690,7 +697,11 @@ static void s_option PARAMS ((int));
static void s_mipsset PARAMS ((int));
static void s_abicalls PARAMS ((int));
static void s_cpload PARAMS ((int));
static void s_cpsetup PARAMS ((int));
static void s_cplocal PARAMS ((int));
static void s_cprestore PARAMS ((int));
static void s_cpreturn PARAMS ((int));
static void s_gpvalue PARAMS ((int));
static void s_gpword PARAMS ((int));
static void s_cpadd PARAMS ((int));
static void s_insn PARAMS ((int));
@ -779,7 +790,11 @@ static const pseudo_typeS mips_pseudo_table[] =
{"livereg", s_ignore, 0},
{"abicalls", s_abicalls, 0},
{"cpload", s_cpload, 0},
{"cpsetup", s_cpsetup, 0},
{"cplocal", s_cplocal, 0},
{"cprestore", s_cprestore, 0},
{"cpreturn", s_cpreturn, 0},
{"gpvalue", s_gpvalue, 0},
{"gpword", s_gpword, 0},
{"cpadd", s_cpadd, 0},
{"insn", s_insn, 0},
@ -4967,14 +4982,17 @@ macro (ip)
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
if (! HAVE_NEWABI)
{
expr1.X_add_number = mips_cprestore_offset;
macro_build ((char *) NULL, &icnt, &expr1,
HAVE_32BIT_ADDRESSES ? "lw" : "ld",
"t,o(b)", GP, (int) BFD_RELOC_LO16, mips_frame_reg);
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,
HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)",
GP, (int) BFD_RELOC_LO16, mips_frame_reg);
}
}
}
else
@ -5067,18 +5085,20 @@ macro (ip)
(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 (! HAVE_NEWABI)
{
if (mips_opts.noreorder)
macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
if (mips_cprestore_offset < 0)
as_warn (_("No .cprestore pseudo-op used in PIC code"));
else
{
if (mips_opts.noreorder)
macro_build ((char *) NULL, &icnt, (expressionS *) NULL,
"nop", "");
expr1.X_add_number = mips_cprestore_offset;
macro_build ((char *) NULL, &icnt, &expr1,
HAVE_32BIT_ADDRESSES ? "lw" : "ld",
"t,o(b)", GP, (int) BFD_RELOC_LO16,
mips_frame_reg);
expr1.X_add_number = mips_cprestore_offset;
macro_build ((char *) NULL, &icnt, &expr1,
HAVE_32BIT_ADDRESSES ? "lw" : "ld", "t,o(b)",
GP, (int) BFD_RELOC_LO16, mips_frame_reg);
}
}
}
else if (mips_pic == EMBEDDED_PIC)
@ -9930,16 +9950,12 @@ md_pcrel_from (fixP)
&& fixP->fx_addsy != (symbolS *) NULL
&& ! S_IS_DEFINED (fixP->fx_addsy))
{
/* This makes a branch to an undefined symbol be a branch to the
current location. */
if (mips_pic == EMBEDDED_PIC)
{
/* This makes a branch to an undefined symbol be a branch to the
current location. */
return 4;
}
return 4;
else
{
return 1;
}
return 1;
}
/* return the address of the delay slot */
@ -10082,6 +10098,13 @@ mips_force_relocation (fixp)
|| fixp->fx_r_type == BFD_RELOC_LO16))
return 1;
if (HAVE_NEWABI
&& S_GET_SEGMENT (fixp->fx_addsy) == bfd_abs_section_ptr
&& (fixp->fx_r_type == BFD_RELOC_MIPS_SUB
|| fixp->fx_r_type == BFD_RELOC_HI16_S
|| fixp->fx_r_type == BFD_RELOC_LO16))
return 1;
return (mips_pic == EMBEDDED_PIC
&& (fixp->fx_pcrel
|| SWITCH_TABLE (fixp)
@ -11069,8 +11092,9 @@ s_cpload (ignore)
expressionS ex;
int icnt = 0;
/* If we are not generating SVR4 PIC code, .cpload is ignored. */
if (mips_pic != SVR4_PIC)
/* If we are not generating SVR4 PIC code, or if this is NewABI code,
.cpload is ignored. */
if (mips_pic != SVR4_PIC || HAVE_NEWABI)
{
s_ignore (0);
return;
@ -11098,6 +11122,119 @@ s_cpload (ignore)
demand_empty_rest_of_line ();
}
/* Handle the .cpsetup pseudo-op defined for NewABI PIC code. The syntax is:
.cpsetup $reg1, offset|$reg2, label
If offset is given, this results in:
sd $gp, offset($sp)
lui $gp, %gp_rel(%neg(%hi(label)))
daddiu $gp, $gp, %gp_rel(%neg(%lo(label)))
addu $gp, $gp, $reg1
If $reg2 is given, this results in:
daddu $reg2, $gp, $0
lui $gp, %gp_rel(%neg(%hi(label)))
daddiu $gp, $gp, %gp_rel(%neg(%lo(label)))
addu $gp, $gp, $reg1
*/
static void
s_cpsetup (ignore)
int ignore ATTRIBUTE_UNUSED;
{
expressionS ex_off;
expressionS ex_sym;
int reg1;
int icnt = 0;
char *sym;
/* If we are not generating SVR4 PIC code, .cpload is ignored.
We also need NewABI support. */
if (mips_pic != SVR4_PIC || ! HAVE_NEWABI)
{
s_ignore (0);
return;
}
reg1 = tc_get_register (0);
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
as_bad (_("missing argument separator ',' for .cpsetup"));
return;
}
else
input_line_pointer++;
SKIP_WHITESPACE ();
if (*input_line_pointer == '$')
mips_cpreturn_register = tc_get_register (0);
else
mips_cpreturn_offset = get_absolute_expression ();
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
as_bad (_("missing argument separator ',' for .cpsetup"));
return;
}
else
input_line_pointer++;
SKIP_WHITESPACE ();
sym = input_line_pointer;
while (ISALNUM (*input_line_pointer))
input_line_pointer++;
*input_line_pointer = 0;
ex_sym.X_op = O_symbol;
ex_sym.X_add_symbol = symbol_find_or_make (sym);
ex_sym.X_op_symbol = NULL;
ex_sym.X_add_number = 0;
if (mips_cpreturn_register == -1)
{
ex_off.X_op = O_constant;
ex_off.X_add_symbol = NULL;
ex_off.X_op_symbol = NULL;
ex_off.X_add_number = mips_cpreturn_offset;
macro_build ((char *) NULL, &icnt, &ex_off, "sd", "t,o(b)",
mips_gp_register, (int) BFD_RELOC_LO16, SP);
}
else
macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "daddu",
"d,v,t", mips_cpreturn_register, mips_gp_register, 0);
macro_build ((char *) NULL, &icnt, &ex_sym, "lui", "t,u", mips_gp_register,
(int) BFD_RELOC_GPREL16);
fix_new (frag_now, (char *) prev_insn_fixp - 4 - frag_now->fr_literal, 0,
NULL, 0, 0, BFD_RELOC_MIPS_SUB);
fix_new (frag_now, (char *) prev_insn_fixp - 4 - frag_now->fr_literal, 0,
NULL, 0, 0, BFD_RELOC_HI16_S);
macro_build ((char *) NULL, &icnt, &ex_sym, "addiu", "t,r,j",
mips_gp_register, mips_gp_register, (int) BFD_RELOC_GPREL16);
fix_new (frag_now, (char *) prev_insn_fixp - 4 - frag_now->fr_literal, 0,
NULL, 0, 0, BFD_RELOC_MIPS_SUB);
fix_new (frag_now, (char *) prev_insn_fixp - 4 - frag_now->fr_literal, 0,
NULL, 0, 0, BFD_RELOC_LO16);
macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "daddu",
"d,v,t", mips_gp_register, mips_gp_register, reg1);
demand_empty_rest_of_line ();
}
static void
s_cplocal (ignore)
int ignore ATTRIBUTE_UNUSED;
{
/* If we are not generating SVR4 PIC code, or if this is not NewABI code,
.cplocal is ignored. */
if (mips_pic != SVR4_PIC || ! HAVE_NEWABI)
{
s_ignore (0);
return;
}
mips_gp_register = tc_get_register (0);
}
/* Handle the .cprestore pseudo-op. This stores $gp into a given
offset from $sp. The offset is remembered, and after making a PIC
call $gp is restored from that location. */
@ -11109,8 +11246,9 @@ s_cprestore (ignore)
expressionS ex;
int icnt = 0;
/* If we are not generating SVR4 PIC code, .cprestore is ignored. */
if (mips_pic != SVR4_PIC)
/* If we are not generating SVR4 PIC code, or if this is NewABI code,
.cprestore is ignored. */
if (mips_pic != SVR4_PIC || HAVE_NEWABI)
{
s_ignore (0);
return;
@ -11130,6 +11268,65 @@ s_cprestore (ignore)
demand_empty_rest_of_line ();
}
/* Handle the .cpreturn pseudo-op defined for NewABI PIC code. If an offset
was given in the preceeding .gpsetup, it results in:
ld $gp, offset($sp)
If a register $reg2 was given there, it results in:
daddiu $gp, $gp, $reg2
*/
static void
s_cpreturn (ignore)
int ignore ATTRIBUTE_UNUSED;
{
expressionS ex;
int icnt = 0;
/* If we are not generating SVR4 PIC code, .cpreturn is ignored.
We also need NewABI support. */
if (mips_pic != SVR4_PIC || ! HAVE_NEWABI)
{
s_ignore (0);
return;
}
if (mips_cpreturn_register == -1)
{
ex.X_op = O_constant;
ex.X_add_symbol = NULL;
ex.X_op_symbol = NULL;
ex.X_add_number = mips_cpreturn_offset;
macro_build ((char *) NULL, &icnt, &ex, "ld", "t,o(b)",
mips_gp_register, (int) BFD_RELOC_LO16, SP);
}
else
macro_build ((char *) NULL, &icnt, (expressionS *) NULL, "daddu",
"d,v,t", mips_gp_register, mips_cpreturn_register, 0);
demand_empty_rest_of_line ();
}
/* Handle the .gpvalue pseudo-op. This is used when generating NewABI PIC
code. It sets the offset to use in gp_rel relocations. */
static void
s_gpvalue (ignore)
int ignore ATTRIBUTE_UNUSED;
{
/* If we are not generating SVR4 PIC code, .gpvalue is ignored.
We also need NewABI support. */
if (mips_pic != SVR4_PIC || ! HAVE_NEWABI)
{
s_ignore (0);
return;
}
mips_cpreturn_offset = get_absolute_expression ();
demand_empty_rest_of_line ();
}
/* Handle the .gpword pseudo-op. This is used when generating PIC
code. It generates a 32 bit GP relative reloc. */
@ -11180,8 +11377,9 @@ s_cpadd (ignore)
int icnt = 0;
int reg;
/* This is ignored when not generating SVR4 PIC code. */
if (mips_pic != SVR4_PIC)
/* This is ignored when not generating SVR4 PIC code or if this is NewABI
code. */
if (mips_pic != SVR4_PIC || HAVE_NEWABI)
{
s_ignore (0);
return;
@ -11361,7 +11559,7 @@ nopic_need_relax (sym, before_relaxing)
if (sym == 0)
return 0;
if (USE_GLOBAL_POINTER_OPT)
if (USE_GLOBAL_POINTER_OPT && g_switch_value > 0)
{
const char *symname;
int change;
@ -11832,7 +12030,8 @@ tc_gen_reloc (section, fixp)
|| fixp->fx_r_type == BFD_RELOC_MIPS_GOT_HI16
|| fixp->fx_r_type == BFD_RELOC_MIPS_GOT_LO16
|| fixp->fx_r_type == BFD_RELOC_MIPS_CALL_HI16
|| fixp->fx_r_type == BFD_RELOC_MIPS_CALL_LO16))
|| fixp->fx_r_type == BFD_RELOC_MIPS_CALL_LO16)
&& ! HAVE_NEWABI)
{
arelent *reloc2;