This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH] microMIPS: Branch swapping support
- From: "Maciej W. Rozycki" <macro at codesourcery dot com>
- To: Richard Sandiford <rdsandiford at googlemail dot com>
- Cc: binutils at sourceware dot org, Chao-ying Fu <fu at mips dot com>, Rich Fuhler <rich at mips dot com>, David Lau <davidlau at mips dot com>, Kevin Mills <kevinm at mips dot com>, Ilie Garbacea <ilie at mips dot com>, Catherine Moore <clm at codesourcery dot com>, Nathan Sidwell <nathan at codesourcery dot com>, Joseph Myers <joseph at codesourcery dot com>
- Date: Mon, 8 Aug 2011 13:35:31 +0100 (BST)
- Subject: Re: [PATCH] microMIPS: Branch swapping support
- References: <alpine.DEB.1.10.1108021835260.4083@tp.orcam.me.uk> <87vcuaq0zp.fsf@firetop.home>
On Sat, 6 Aug 2011, Richard Sandiford wrote:
> > /* We have no flag to mark the read from "y", so we use TRAP to disable
> > delay slot scheduling of ALNV.PS altogether. */
> > {"alnv.ps", "D,V,T,y", 0x54000019, 0xfc00003f, TRAP|WR_D|RD_S|RD_T|FP_D, 0, I1 },
> > -{"and", "mf,mt,mg", 0x4480, 0xffc0, 0, MOD_mf|MOD_mg, I1 },
> > -{"and", "mf,mg,mx", 0x4480, 0xffc0, 0, MOD_mf|MOD_mg, I1 },
> > +{"and", "mf,mt,mg", 0x4480, 0xffc0, 0, WR_mf|RD_mg, I1 },
> > +{"and", "mf,mg,mx", 0x4480, 0xffc0, 0, WR_mf|RD_mg, I1 },
>
> Unless I'm missing something, it looks like this loses the read from mf.
> Same for OR and XOR.
Indeed, sigh... Thanks for catching it.
And as we've run out of pinfo bits, here's an update that brings
INSN2_MOD_GPR_MF back, except that the opcode table now uses separate
RD_mf and WR_mf macros, similarly to INSN2_MOD_GPR_MD vs RD_md/WR_md.
This will make it easier to convert to separate pinfo bits if we ever get
some more. The new arrangement penalises the short form of the NOT
instruction (and some NOR cases that decay to same) that is now treated as
if it read its destination register.
OK with this update?
2011-08-08 Maciej W. Rozycki <macro@codesourcery.com>
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.
Maciej
binutils-gas-umips-swap-fix.diff
Index: binutils-fsf-trunk-quilt/opcodes/micromips-opc.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/opcodes/micromips-opc.c 2011-08-08 01:30:32.000000000 +0100
+++ binutils-fsf-trunk-quilt/opcodes/micromips-opc.c 2011-08-08 01:16:44.000000000 +0100
@@ -39,7 +39,8 @@
#define RD_md INSN2_MOD_GPR_MD
#define WR_md INSN2_MOD_GPR_MD
#define RD_me INSN2_READ_GPR_ME
-#define WR_mf INSN2_WRITE_GPR_MF
+#define RD_mf INSN2_MOD_GPR_MF
+#define WR_mf INSN2_MOD_GPR_MF
#define RD_mg INSN2_READ_GPR_MG
#define WR_mhi INSN2_WRITE_GPR_MHI
#define RD_mj INSN2_READ_GPR_MJ
@@ -163,8 +164,8 @@ const struct mips_opcode micromips_opcod
/* We have no flag to mark the read from "y", so we use TRAP to disable
delay slot scheduling of ALNV.PS altogether. */
{"alnv.ps", "D,V,T,y", 0x54000019, 0xfc00003f, TRAP|WR_D|RD_S|RD_T|FP_D, 0, I1 },
-{"and", "mf,mt,mg", 0x4480, 0xffc0, 0, WR_mf|RD_mg, I1 },
-{"and", "mf,mg,mx", 0x4480, 0xffc0, 0, WR_mf|RD_mg, I1 },
+{"and", "mf,mt,mg", 0x4480, 0xffc0, 0, WR_mf|RD_mf|RD_mg, I1 },
+{"and", "mf,mg,mx", 0x4480, 0xffc0, 0, WR_mf|RD_mf|RD_mg, I1 },
{"and", "d,v,t", 0x00000250, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 },
{"and", "t,r,I", 0, (int) M_AND_I, INSN_MACRO, 0, I1 },
{"andi", "md,mc,mC", 0x2c00, 0xfc00, 0, WR_md|RD_mc, I1 },
@@ -723,8 +724,8 @@ const struct mips_opcode micromips_opcod
{"nor", "t,r,I", 0, (int) M_NOR_I, INSN_MACRO, 0, I1 },
{"or", "mp,mj,mz", 0x0c00, 0xfc00, 0, WR_mp|RD_mj, I1 }, /* move */
{"or", "mp,mz,mj", 0x0c00, 0xfc00, 0, WR_mp|RD_mj, I1 }, /* move */
-{"or", "mf,mt,mg", 0x44c0, 0xffc0, 0, WR_mf|RD_mg, I1 },
-{"or", "mf,mg,mx", 0x44c0, 0xffc0, 0, WR_mf|RD_mg, I1 },
+{"or", "mf,mt,mg", 0x44c0, 0xffc0, 0, WR_mf|RD_mf|RD_mg, I1 },
+{"or", "mf,mg,mx", 0x44c0, 0xffc0, 0, WR_mf|RD_mf|RD_mg, I1 },
{"or", "d,v,t", 0x00000290, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 },
{"or", "t,r,I", 0, (int) M_OR_I, INSN_MACRO, 0, I1 },
{"ori", "mp,mj,mZ", 0x0c00, 0xfc00, 0, WR_mp|RD_mj, I1 }, /* move */
@@ -949,8 +950,8 @@ const struct mips_opcode micromips_opcod
{"wait", "B", 0x0000937c, 0xfc00ffff, NODS, 0, I1 },
{"wrpgpr", "t,r", 0x0000f17c, 0xfc00ffff, RD_s, 0, I1 },
{"wsbh", "t,r", 0x00007b3c, 0xfc00ffff, WR_t|RD_s, 0, I1 },
-{"xor", "mf,mt,mg", 0x4440, 0xffc0, 0, WR_mf|RD_mg, I1 },
-{"xor", "mf,mg,mx", 0x4440, 0xffc0, 0, WR_mf|RD_mg, I1 },
+{"xor", "mf,mt,mg", 0x4440, 0xffc0, 0, WR_mf|RD_mf|RD_mg, I1 },
+{"xor", "mf,mg,mx", 0x4440, 0xffc0, 0, WR_mf|RD_mf|RD_mg, I1 },
{"xor", "d,v,t", 0x00000310, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I1 },
{"xor", "t,r,I", 0, (int) M_XOR_I, INSN_MACRO, 0, I1 },
{"xori", "t,r,i", 0x70000000, 0xfc000000, WR_t|RD_s, 0, I1 },
Index: binutils-fsf-trunk-quilt/gas/config/tc-mips.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/gas/config/tc-mips.c 2011-08-08 01:30:32.000000000 +0100
+++ binutils-fsf-trunk-quilt/gas/config/tc-mips.c 2011-08-08 01:17:55.000000000 +0100
@@ -2899,6 +2899,8 @@ gpr_mod_mask (const struct mips_cl_insn
{
if (pinfo2 & INSN2_MOD_GPR_MD)
mask |= 1 << micromips_to_32_reg_d_map[EXTRACT_OPERAND (1, MD, *ip)];
+ if (pinfo2 & INSN2_MOD_GPR_MF)
+ mask |= 1 << micromips_to_32_reg_f_map[EXTRACT_OPERAND (1, MF, *ip)];
if (pinfo2 & INSN2_MOD_SP)
mask |= 1 << SP;
}
@@ -3018,8 +3020,6 @@ gpr_write_mask (const struct mips_cl_ins
{
if (pinfo2 & INSN2_WRITE_GPR_MB)
mask |= 1 << micromips_to_32_reg_b_map[EXTRACT_OPERAND (1, MB, *ip)];
- if (pinfo2 & INSN2_WRITE_GPR_MF)
- mask |= 1 << micromips_to_32_reg_f_map[EXTRACT_OPERAND (1, MF, *ip)];
if (pinfo2 & INSN2_WRITE_GPR_MHI)
{
mask |= 1 << micromips_to_32_reg_h_map[EXTRACT_OPERAND (1, MH, *ip)];
Index: binutils-fsf-trunk-quilt/include/opcode/mips.h
===================================================================
--- binutils-fsf-trunk-quilt.orig/include/opcode/mips.h 2011-08-08 01:30:32.000000000 +0100
+++ binutils-fsf-trunk-quilt/include/opcode/mips.h 2011-08-08 01:18:37.000000000 +0100
@@ -634,8 +634,8 @@ struct mips_opcode
#define INSN2_MOD_GPR_MD 0x00008000
/* Reads the general purpose register in MICROMIPSOP_*_ME. */
#define INSN2_READ_GPR_ME 0x00010000
-/* Modifies the general purpose register in MICROMIPSOP_*_MF. */
-#define INSN2_WRITE_GPR_MF 0x00020000
+/* Reads/writes the general purpose register in MICROMIPSOP_*_MF. */
+#define INSN2_MOD_GPR_MF 0x00020000
/* Reads the general purpose register in MICROMIPSOP_*_MG. */
#define INSN2_READ_GPR_MG 0x00040000
/* Reads the general purpose register in MICROMIPSOP_*_MJ. */