diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index fcf06ac..72dfa64 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -865,6 +865,9 @@ static int mips_fix_vr4130; /* ...likewise -mfix-24k. */ static int mips_fix_24k; +/* ...likewise -mfix-pmc */ +static int mips_fix_pmc; + /* ...likewise -mfix-cn63xxp1 */ static bfd_boolean mips_fix_cn63xxp1; @@ -1354,6 +1357,8 @@ enum options OPTION_MNO_7000_HILO_FIX, OPTION_FIX_24K, OPTION_NO_FIX_24K, + OPTION_FIX_PMC, + OPTION_NO_FIX_PMC, OPTION_FIX_LOONGSON2F_JUMP, OPTION_NO_FIX_LOONGSON2F_JUMP, OPTION_FIX_LOONGSON2F_NOP, @@ -1469,6 +1474,8 @@ struct option md_longopts[] = {"mno-fix-vr4130", no_argument, NULL, OPTION_NO_FIX_VR4130}, {"mfix-24k", no_argument, NULL, OPTION_FIX_24K}, {"mno-fix-24k", no_argument, NULL, OPTION_NO_FIX_24K}, + {"mfix-pmc", no_argument, NULL, OPTION_FIX_PMC}, + {"mno-fix-pmc", no_argument, NULL, OPTION_NO_FIX_PMC}, {"mfix-cn63xxp1", no_argument, NULL, OPTION_FIX_CN63XXP1}, {"mno-fix-cn63xxp1", no_argument, NULL, OPTION_NO_FIX_CN63XXP1}, @@ -5559,8 +5566,10 @@ classify_vr4120_insn (const char *name) return NUM_FIX_VR4120_CLASSES; } -#define INSN_ERET 0x42000018 -#define INSN_DERET 0x4200001f +#define INSN_ERET 0x42000018 +#define INSN_DERET 0x4200001f +#define INSN_DMULT 0x1c +#define INSN_DMULTU 0x1d /* Return the number of instructions that must separate INSN1 and INSN2, where INSN1 is the earlier instruction. Return the worst-case value @@ -5611,6 +5620,19 @@ insns_between (const struct mips_cl_insn *insn1, } } + /* If we're working around PMC errata, there must be three nops between + a dmult and a load instruction. */ + + if (mips_fix_pmc && !mips_opts.micromips) + { + if ((insn1->insn_opcode & insn1->insn_mo->mask) == INSN_DMULT + || (insn1->insn_opcode & insn1->insn_mo->mask) == INSN_DMULTU) + { + if (pinfo2 & INSN_LOAD_MEMORY) + return 3; + } + } + /* If working around VR4120 errata, check for combinations that need a single intervening instruction. */ if (mips_fix_vr4120 && !mips_opts.micromips) @@ -13592,6 +13614,14 @@ md_parse_option (int c, char *arg) mips_fix_24k = 0; break; + case OPTION_FIX_PMC: + mips_fix_pmc = 1; + break; + + case OPTION_NO_FIX_PMC: + mips_fix_pmc = 0; + break; + case OPTION_FIX_LOONGSON2F_JUMP: mips_fix_loongson2f_jump = TRUE; break; diff --git a/gas/testsuite/gas/mips/fix-pmc-1.d b/gas/testsuite/gas/mips/fix-pmc-1.d new file mode 100644 index 0000000..10ec28a --- /dev/null +++ b/gas/testsuite/gas/mips/fix-pmc-1.d @@ -0,0 +1,21 @@ +#as: -mfix-pmc -mgp64 +#objdump: -dz --prefix-addresses +#name: MIPS PMC workarounds + +.*file format.* + +Disassembly.* + +0+0000 <[^>]*> move v0,a0 +0+0004 <[^>]*> dmult a2,v1 +0+0008 <[^>]*> nop +0+000c <[^>]*> nop +0+0010 <[^>]*> nop +0+0014 <[^>]*> ld a3,0\(s8\) +0+0018 <[^>]*> ld a0,0\(s8\) +0+001c <[^>]*> move a0,a3 +0+0020 <[^>]*> dmult v0,a3 +0+0024 <[^>]*> nop +0+0028 <[^>]*> nop +0+002c <[^>]*> nop +0+0030 <[^>]*> ld a0,0\(s8\) diff --git a/gas/testsuite/gas/mips/fix-pmc-1.s b/gas/testsuite/gas/mips/fix-pmc-1.s new file mode 100644 index 0000000..1b65438 --- /dev/null +++ b/gas/testsuite/gas/mips/fix-pmc-1.s @@ -0,0 +1,9 @@ + .text +test1: + move $2,$4 + dmult $6,$3 + ld $7,0($fp) + ld $4,0($fp) + move $4,$7 + dmult $2,$7 + ld $4,0($fp) diff --git a/gas/testsuite/gas/mips/fix-pmc-2.d b/gas/testsuite/gas/mips/fix-pmc-2.d new file mode 100644 index 0000000..11d3e1d --- /dev/null +++ b/gas/testsuite/gas/mips/fix-pmc-2.d @@ -0,0 +1,57 @@ +#as: -mfix-pmc -mgp64 +#objdump: -dz --prefix-addresses +#name: MIPS PMC workarounds test 2 +#source: fix-pmc-2.s + +.*file format.* + +Disassembly.* +0+0000 <[^>]*> move v0,a0 +0+0004 <[^>]*> dmultu a1,a3 +0+0008 <[^>]*> nop +0+000c <[^>]*> nop +0+0010 <[^>]*> nop +0+0014 <[^>]*> lb a0,0\(s8\) +0+0018 <[^>]*> dmult a2,v1 +0+001c <[^>]*> nop +0+0020 <[^>]*> nop +0+0024 <[^>]*> nop +0+0028 <[^>]*> lbu a3,0\(s8\) +0+002c <[^>]*> move v0,a0 +0+0030 <[^>]*> dmultu a1,a3 +0+0034 <[^>]*> addiu a0,s8,0 +0+0038 <[^>]*> move v0,a0 +0+003c <[^>]*> dmult a2,v1 +0+0040 <[^>]*> nop +0+0044 <[^>]*> nop +0+0048 <[^>]*> nop +0+004c <[^>]*> lh a3,0\(s8\) +0+0050 <[^>]*> dmultu a1,a3 +0+0054 <[^>]*> nop +0+0058 <[^>]*> nop +0+005c <[^>]*> nop +0+0060 <[^>]*> lhu a0,0\(s8\) +0+0064 <[^>]*> dmult a2,v1 +0+0068 <[^>]*> nop +0+006c <[^>]*> nop +0+0070 <[^>]*> nop +0+0074 <[^>]*> ll a3,0\(s8\) +0+0078 <[^>]*> dmultu a1,a3 +0+007c <[^>]*> nop +0+0080 <[^>]*> nop +0+0084 <[^>]*> nop +0+0088 <[^>]*> lld a0,0\(s8\) +0+008c <[^>]*> dmultu a1,a3 +0+0090 <[^>]*> nop +0+0094 <[^>]*> nop +0+0098 <[^>]*> nop +0+009c <[^>]*> lw a0,0\(s8\) +0+00a0 <[^>]*> dmult a2,v1 +0+00a4 <[^>]*> nop +0+00a8 <[^>]*> nop +0+00ac <[^>]*> nop +0+00b0 <[^>]*> lwr a3,0\(s8\) +0+00b4 <[^>]*> dmultu a1,a3 +0+00b8 <[^>]*> nop +0+00bc <[^>]*> nop +0+00c0 <[^>]*> nop diff --git a/gas/testsuite/gas/mips/fix-pmc-2.s b/gas/testsuite/gas/mips/fix-pmc-2.s new file mode 100644 index 0000000..0411e7c --- /dev/null +++ b/gas/testsuite/gas/mips/fix-pmc-2.s @@ -0,0 +1,24 @@ + .text +test2: + move $2,$4 + dmultu $5,$7 + lb $4,0($fp) + dmult $6,$3 + lbu $7,0($fp) + move $2,$4 + dmultu $5,$7 + lca $4,0($fp) + move $2,$4 + dmult $6,$3 + lh $7,0($fp) + dmultu $5,$7 + lhu $4,0($fp) + dmult $6,$3 + ll $7,0($fp) + dmultu $5,$7 + lld $4,0($fp) + dmultu $5,$7 + lw $4,0($fp) + dmult $6,$3 + lwr $7,0($fp) + dmultu $5,$7 diff --git a/gas/testsuite/gas/mips/micromips@fix-pmc-1.d b/gas/testsuite/gas/mips/micromips@fix-pmc-1.d new file mode 100644 index 0000000..5f14266 --- /dev/null +++ b/gas/testsuite/gas/mips/micromips@fix-pmc-1.d @@ -0,0 +1,16 @@ +#as: -mfix-pmc -mgp64 +#objdump: -dz --prefix-addresses +#name: MIPS PMC workarounds +#source: fix-pmc-1.s + +.*file format.* + +Disassembly.* + +0+0000 <[^>]*> move v0,a0 +0+0002 <[^>]*> dmult a2,v1 +0+0006 <[^>]*> ld a3,0\(s8\) +0+000a <[^>]*> ld a0,0\(s8\) +0+000e <[^>]*> move a0,a3 +0+0010 <[^>]*> dmult v0,a3 +0+0014 <[^>]*> ld a0,0\(s8\) diff --git a/gas/testsuite/gas/mips/micromips@fix-pmc-2.d b/gas/testsuite/gas/mips/micromips@fix-pmc-2.d new file mode 100644 index 0000000..6e22ec1 --- /dev/null +++ b/gas/testsuite/gas/mips/micromips@fix-pmc-2.d @@ -0,0 +1,31 @@ +#as: -mfix-pmc -mgp64 +#objdump: -dz --prefix-addresses +#name: MIPS PMC workarounds test 2 +#source: fix-pmc-2.s + +.*file format.* + +Disassembly.* +0+0000 <[^>]*> move v0,a0 +0+0002 <[^>]*> dmultu a1,a3 +0+0006 <[^>]*> lb a0,0\(s8\) +0+000a <[^>]*> dmult a2,v1 +0+000e <[^>]*> lbu a3,0\(s8\) +0+0012 <[^>]*> move v0,a0 +0+0014 <[^>]*> dmultu a1,a3 +0+0018 <[^>]*> addiu a0,s8,0 +0+001c <[^>]*> move v0,a0 +0+001e <[^>]*> dmult a2,v1 +0+0022 <[^>]*> lh a3,0\(s8\) +0+0026 <[^>]*> dmultu a1,a3 +0+002a <[^>]*> lhu a0,0\(s8\) +0+002e <[^>]*> dmult a2,v1 +0+0032 <[^>]*> ll a3,0\(s8\) +0+0036 <[^>]*> dmultu a1,a3 +0+003a <[^>]*> lld a0,0\(s8\) +0+003e <[^>]*> dmultu a1,a3 +0+0042 <[^>]*> lw a0,0\(s8\) +0+0046 <[^>]*> dmult a2,v1 +0+004a <[^>]*> lwr a3,0\(s8\) +0+004e <[^>]*> dmultu a1,a3 +0+0052 <[^>]*> nop diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp index d632c4f..e1e8b40 100644 --- a/gas/testsuite/gas/mips/mips.exp +++ b/gas/testsuite/gas/mips/mips.exp @@ -529,6 +529,8 @@ if { [istarget mips*-*-vxworks*] } { run_dump_test "eret-1" run_dump_test "eret-2" run_dump_test "eret-3" + run_dump_test_arches "fix-pmc-1" [mips_arch_list_matching mips3 !singlefloat] + run_dump_test_arches "fix-pmc-2" [mips_arch_list_matching mips3 !singlefloat] run_dump_test_arches "24k-branch-delay-1" \ [mips_arch_list_matching mips1] run_dump_test_arches "24k-triple-stores-1" \