diff options
author | Maciej W. Rozycki <macro@linux-mips.org> | 2011-08-09 14:25:29 +0000 |
---|---|---|
committer | Maciej W. Rozycki <macro@linux-mips.org> | 2011-08-09 14:25:29 +0000 |
commit | 2b0c8b40edb06c073ce8bb358239cc1a5c6653a5 (patch) | |
tree | 3563d1a52c9e5d7f5c23d6cd1fd6d1082d0b76eb /gas/config/tc-mips.c | |
parent | 401a70b8da409365b70f8e5e8544fa0e24c486fd (diff) | |
download | gdb-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.c | 85 |
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; |