aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-mips.c
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@linux-mips.org>2011-08-09 14:25:29 +0000
committerMaciej W. Rozycki <macro@linux-mips.org>2011-08-09 14:25:29 +0000
commit2b0c8b40edb06c073ce8bb358239cc1a5c6653a5 (patch)
tree3563d1a52c9e5d7f5c23d6cd1fd6d1082d0b76eb /gas/config/tc-mips.c
parent401a70b8da409365b70f8e5e8544fa0e24c486fd (diff)
downloadgdb-2b0c8b40edb06c073ce8bb358239cc1a5c6653a5.zip
gdb-2b0c8b40edb06c073ce8bb358239cc1a5c6653a5.tar.gz
gdb-2b0c8b40edb06c073ce8bb358239cc1a5c6653a5.tar.bz2
include/opcode/
* mips.h (INSN_WRITE_GPR_S, INSN2_WRITE_GPR_MB): New macros. (INSN2_READ_GPR_MC, INSN2_READ_GPR_ME): Likewise. (INSN2_WRITE_GPR_MF, INSN2_READ_GPR_MG): Likewise. (INSN2_READ_GPR_MJ, INSN2_WRITE_GPR_MJ): Likewise. (INSN2_READ_GPR_MP, INSN2_WRITE_GPR_MP): Likewise. (INSN2_READ_GPR_MQ, INSN2_WRITE_GPR_MHI): Likewise. (INSN2_READ_GPR_MMN): Likewise. (INSN2_READ_FPR_D): Change the bit used. (INSN2_MOD_GPR_MD, INSN2_MOD_GPR_MF): Likewise. (INSN2_MOD_SP, INSN2_READ_GPR_31, INSN2_READ_GP): Likewise. (INSN2_READ_PC, INSN2_UNCOND_BRANCH): Likewise. (INSN2_COND_BRANCH): Likewise. (INSN2_WRITE_GPR_S, INSN2_MOD_GPR_MB): Remove macros. (INSN2_MOD_GPR_MC, INSN2_MOD_GPR_ME, INSN2_MOD_GPR_MG): Likewise. (INSN2_MOD_GPR_MJ, INSN2_MOD_GPR_MP, INSN2_MOD_GPR_MQ): Likewise. (INSN2_MOD_GPR_MHI, INSN2_MOD_GPR_MM): Likewise. (INSN2_MOD_GPR_MN): Likewise. gas/ * config/tc-mips.c (gpr_mod_mask): Remove INSN2_MOD_GPR_MB, INSN2_MOD_GPR_MC, INSN2_MOD_GPR_ME, INSN2_MOD_GPR_MG, INSN2_MOD_GPR_MHI, INSN2_MOD_GPR_MJ, INSN2_MOD_GPR_MM, INSN2_MOD_GPR_MN, INSN2_MOD_GPR_MP and INSN2_MOD_GPR_MQ opcode register use checks. (gpr_read_mask): Add INSN2_READ_GPR_MC, INSN2_READ_GPR_ME INSN2_READ_GPR_MG, INSN2_READ_GPR_MJ, INSN2_READ_GPR_MMN, INSN2_READ_GPR_MP and INSN2_READ_GPR_MQ opcode register use checks. (gpr_write_mask): Replace INSN2_WRITE_GPR_S opcode register use flag with INSN_WRITE_GPR_S. Add INSN2_WRITE_GPR_MB, INSN2_WRITE_GPR_MHI, INSN2_WRITE_GPR_MJ and INSN2_WRITE_GPR_MP opcode register use checks. (can_swap_branch_p): Enable microMIPS branch swapping. (append_insn): Likewise. gas/testsuite/ * gas/mips/micromips.d: Update according to changes to enable microMIPS branch swapping. * gas/mips/micromips-trap.d: Likewise. * gas/mips/micromips@jal-svr4pic.d: Likewise. * gas/mips/micromips@loc-swap.d: Likewise. * gas/mips/micromips@loc-swap-dis.d: Likewise. opcodes/ * micromips-opc.c (MOD_mb, MOD_mc, MOD_md): Remove macros. (MOD_me, MOD_mf, MOD_mg, MOD_mhi, MOD_mj, MOD_ml): Likewise. (MOD_mm, MOD_mn, MOD_mp, MOD_mq, MOD_sp): Likewise. (WR_mb, RD_mc, RD_md, WR_md, RD_me, RD_mf, WR_mf): New macros. (RD_mg, WR_mhi, RD_mj, WR_mj, RD_ml, RD_mmn): Likewise. (RD_mp, WR_mp, RD_mq, RD_sp, WR_sp): Likewise. (WR_s): Update macro. (micromips_opcodes): Update register use flags of: "addiu", "addiupc", "addiur1sp", "addiur2", "addius5", "addiusp", "addu", "and", "andi", "beq", "beqz", "bne", "bnez", "di", "ei", "j", "jalr", "jalrs", "jr", "jraddiusp", "jrc", "lbu", "lhu", "li", "lui", "lw", "lwm", "mfhi", "mflo", "move", "movep", "not", "nor", "or", "ori", "sb", "sh", "sll", "srl", "subu", "sw", "swm" and "xor" instructions.
Diffstat (limited to 'gas/config/tc-mips.c')
-rw-r--r--gas/config/tc-mips.c85
1 files changed, 47 insertions, 38 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index eba45ec..08c1c02 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -2942,33 +2942,10 @@ gpr_mod_mask (const struct mips_cl_insn *ip)
pinfo2 = ip->insn_mo->pinfo2;
if (mips_opts.micromips)
{
- if (pinfo2 & INSN2_MOD_GPR_MB)
- mask |= 1 << micromips_to_32_reg_b_map[EXTRACT_OPERAND (1, MB, *ip)];
- if (pinfo2 & INSN2_MOD_GPR_MC)
- mask |= 1 << micromips_to_32_reg_c_map[EXTRACT_OPERAND (1, MC, *ip)];
if (pinfo2 & INSN2_MOD_GPR_MD)
mask |= 1 << micromips_to_32_reg_d_map[EXTRACT_OPERAND (1, MD, *ip)];
- if (pinfo2 & INSN2_MOD_GPR_ME)
- mask |= 1 << micromips_to_32_reg_e_map[EXTRACT_OPERAND (1, ME, *ip)];
if (pinfo2 & INSN2_MOD_GPR_MF)
mask |= 1 << micromips_to_32_reg_f_map[EXTRACT_OPERAND (1, MF, *ip)];
- if (pinfo2 & INSN2_MOD_GPR_MG)
- mask |= 1 << micromips_to_32_reg_g_map[EXTRACT_OPERAND (1, MG, *ip)];
- if (pinfo2 & INSN2_MOD_GPR_MHI)
- {
- mask |= 1 << micromips_to_32_reg_h_map[EXTRACT_OPERAND (1, MH, *ip)];
- mask |= 1 << micromips_to_32_reg_i_map[EXTRACT_OPERAND (1, MI, *ip)];
- }
- if (pinfo2 & INSN2_MOD_GPR_MJ)
- mask |= 1 << EXTRACT_OPERAND (1, MJ, *ip);
- if (pinfo2 & INSN2_MOD_GPR_MM)
- mask |= 1 << micromips_to_32_reg_m_map[EXTRACT_OPERAND (1, MM, *ip)];
- if (pinfo2 & INSN2_MOD_GPR_MN)
- mask |= 1 << micromips_to_32_reg_n_map[EXTRACT_OPERAND (1, MN, *ip)];
- if (pinfo2 & INSN2_MOD_GPR_MP)
- mask |= 1 << EXTRACT_OPERAND (1, MP, *ip);
- if (pinfo2 & INSN2_MOD_GPR_MQ)
- mask |= 1 << micromips_to_32_reg_q_map[EXTRACT_OPERAND (1, MQ, *ip)];
if (pinfo2 & INSN2_MOD_SP)
mask |= 1 << SP;
}
@@ -3019,6 +2996,26 @@ gpr_read_mask (const struct mips_cl_insn *ip)
if (pinfo2 & INSN2_READ_GPR_Z)
mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, RZ, *ip);
}
+ if (mips_opts.micromips)
+ {
+ if (pinfo2 & INSN2_READ_GPR_MC)
+ mask |= 1 << micromips_to_32_reg_c_map[EXTRACT_OPERAND (1, MC, *ip)];
+ if (pinfo2 & INSN2_READ_GPR_ME)
+ mask |= 1 << micromips_to_32_reg_e_map[EXTRACT_OPERAND (1, ME, *ip)];
+ if (pinfo2 & INSN2_READ_GPR_MG)
+ mask |= 1 << micromips_to_32_reg_g_map[EXTRACT_OPERAND (1, MG, *ip)];
+ if (pinfo2 & INSN2_READ_GPR_MJ)
+ mask |= 1 << EXTRACT_OPERAND (1, MJ, *ip);
+ if (pinfo2 & INSN2_READ_GPR_MMN)
+ {
+ mask |= 1 << micromips_to_32_reg_m_map[EXTRACT_OPERAND (1, MM, *ip)];
+ mask |= 1 << micromips_to_32_reg_n_map[EXTRACT_OPERAND (1, MN, *ip)];
+ }
+ if (pinfo2 & INSN2_READ_GPR_MP)
+ mask |= 1 << EXTRACT_OPERAND (1, MP, *ip);
+ if (pinfo2 & INSN2_READ_GPR_MQ)
+ mask |= 1 << micromips_to_32_reg_q_map[EXTRACT_OPERAND (1, MQ, *ip)];
+ }
/* Don't include register 0. */
return mask & ~1;
}
@@ -3057,13 +3054,27 @@ gpr_write_mask (const struct mips_cl_insn *ip)
mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, RD, *ip);
if (pinfo & INSN_WRITE_GPR_T)
mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, RT, *ip);
- if (pinfo2 & INSN2_WRITE_GPR_S)
+ if (pinfo & INSN_WRITE_GPR_S)
mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, RS, *ip);
if (pinfo & INSN_WRITE_GPR_31)
mask |= 1 << RA;
if (pinfo2 & INSN2_WRITE_GPR_Z)
mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, RZ, *ip);
}
+ if (mips_opts.micromips)
+ {
+ if (pinfo2 & INSN2_WRITE_GPR_MB)
+ mask |= 1 << micromips_to_32_reg_b_map[EXTRACT_OPERAND (1, MB, *ip)];
+ if (pinfo2 & INSN2_WRITE_GPR_MHI)
+ {
+ mask |= 1 << micromips_to_32_reg_h_map[EXTRACT_OPERAND (1, MH, *ip)];
+ mask |= 1 << micromips_to_32_reg_i_map[EXTRACT_OPERAND (1, MI, *ip)];
+ }
+ if (pinfo2 & INSN2_WRITE_GPR_MJ)
+ mask |= 1 << EXTRACT_OPERAND (1, MJ, *ip);
+ if (pinfo2 & INSN2_WRITE_GPR_MP)
+ mask |= 1 << EXTRACT_OPERAND (1, MP, *ip);
+ }
/* Don't include register 0. */
return mask & ~1;
}
@@ -3666,12 +3677,9 @@ fix_loongson2f (struct mips_cl_insn * ip)
static bfd_boolean
can_swap_branch_p (struct mips_cl_insn *ip)
{
- unsigned long pinfo, pinfo2, prev_pinfo;
+ unsigned long pinfo, pinfo2, prev_pinfo, prev_pinfo2;
unsigned int gpr_read, gpr_write, prev_gpr_read, prev_gpr_write;
- /* For microMIPS, disable reordering. */
- if (mips_opts.micromips)
- return FALSE;
/* -O2 and above is required for this optimization. */
if (mips_optimize < 2)
@@ -3771,8 +3779,11 @@ can_swap_branch_p (struct mips_cl_insn *ip)
return FALSE;
/* If the previous instruction uses the PC, we can not swap. */
+ prev_pinfo2 = history[0].insn_mo->pinfo2;
if (mips_opts.mips16 && (prev_pinfo & MIPS16_INSN_READ_PC))
return FALSE;
+ if (mips_opts.micromips && (prev_pinfo2 & INSN2_READ_PC))
+ return FALSE;
/* If the previous instruction has an incorrect size for a fixed
branch delay slot in microMIPS mode, we cannot swap. */
@@ -3973,6 +3984,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
bfd_boolean relaxed_branch = FALSE;
enum append_method method;
bfd_boolean relax32;
+ int branch_disp;
if (mips_fix_loongson2f && !HAVE_CODE_COMPRESSION)
fix_loongson2f (ip);
@@ -4164,6 +4176,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
}
method = get_append_method (ip);
+ branch_disp = method == APPEND_SWAP ? insn_length (history) : 0;
#ifdef OBJ_ELF
/* The value passed to dwarf2_emit_insn is the distance between
@@ -4181,8 +4194,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
and for MIPS16/microMIPS code also prevents a debugger from
placing a breakpoint in the middle of the branch (and corrupting
code if software breakpoints are used). */
- dwarf2_emit_insn ((HAVE_CODE_COMPRESSION ? -1 : 0)
- + (method == APPEND_SWAP ? insn_length (history) : 0));
+ dwarf2_emit_insn ((HAVE_CODE_COMPRESSION ? -1 : 0) + branch_disp);
#endif
relax32 = (mips_relax_branch
@@ -4236,6 +4248,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
gas_assert (address_expr != NULL);
gas_assert (!mips_relax.sequence);
+ relaxed_branch = TRUE;
length32 = relaxed_micromips_32bit_branch_length (NULL, NULL, uncond);
add_relaxed_insn (ip, relax32 ? length32 : 4, relax16 ? 2 : 4,
RELAX_MICROMIPS_ENCODE (type, AT, uncond, compact, al,
@@ -4450,25 +4463,21 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
move_insn (ip, delay.frag, delay.where);
move_insn (&delay, ip->frag, ip->where + insn_length (ip));
}
- else if (mips_opts.micromips)
- {
- /* We don't reorder for micromips. */
- abort ();
- }
else if (relaxed_branch)
{
/* Add the delay slot instruction to the end of the
current frag and shrink the fixed part of the
original frag. If the branch occupies the tail of
the latter, move it backwards to cover the gap. */
- delay.frag->fr_fix -= 4;
+ delay.frag->fr_fix -= branch_disp;
if (delay.frag == ip->frag)
- move_insn (ip, ip->frag, ip->where - 4);
+ move_insn (ip, ip->frag, ip->where - branch_disp);
add_fixed_insn (&delay);
}
else
{
- move_insn (&delay, ip->frag, ip->where);
+ move_insn (&delay, ip->frag,
+ ip->where - branch_disp + insn_length (ip));
move_insn (ip, history[0].frag, history[0].where);
}
history[0] = *ip;