This patch adds LWL/LWR, SWL/SWR instructions with their corresponding tests. gcc/ChangeLog: * config/mips/mips.cc(mips_expand_ins_as_unaligned_store): Add logics for generating instruction. * config/mips/mips.h(ISA_HAS_LWL_LWR): Add clause for ISA_HAS_MIPS16E2. * config/mips/mips.md(mov_l): Generates instructions. (mov_r): Same as above. (mov_l): Adjusted for the conditions above. (mov_r): Same as above. (mov_l_mips16e2): Add machine description for `define_insn mov_l_mips16e2`. (mov_r_mips16e2): Add machine description for `define_insn mov_r_mips16e2`. gcc/testsuite/ChangeLog: * gcc.target/mips/mips16e2.c: New tests for mips16e2. --- gcc/config/mips/mips.cc | 15 ++- gcc/config/mips/mips.h | 2 +- gcc/config/mips/mips.md | 43 +++++++-- gcc/testsuite/gcc.target/mips/mips16e2.c | 116 +++++++++++++++++++++++ 4 files changed, 168 insertions(+), 8 deletions(-) diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc index 0792f89cab4..275efc5a390 100644 --- a/gcc/config/mips/mips.cc +++ b/gcc/config/mips/mips.cc @@ -8603,12 +8603,25 @@ mips_expand_ins_as_unaligned_store (rtx dest, rtx src, HOST_WIDE_INT width, return false; mode = int_mode_for_size (width, 0).require (); - src = gen_lowpart (mode, src); + if (TARGET_MIPS16 + && src == const0_rtx) + src = force_reg (mode, src); + else + src = gen_lowpart (mode, src); + if (mode == DImode) { + if (TARGET_MIPS16) + gcc_unreachable (); emit_insn (gen_mov_sdl (dest, src, left)); emit_insn (gen_mov_sdr (copy_rtx (dest), copy_rtx (src), right)); } + else if (TARGET_MIPS16) + { + emit_insn (gen_mov_swl_mips16e2 (dest, src, left)); + emit_insn (gen_mov_swr_mips16e2 (copy_rtx (dest), copy_rtx (src), + right)); + } else { emit_insn (gen_mov_swl (dest, src, left)); diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index cab5ff422a8..a5c121088b7 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -1180,7 +1180,7 @@ struct mips_cpu_info { && (MODE) == V2SFmode)) \ && !TARGET_MIPS16) -#define ISA_HAS_LWL_LWR (mips_isa_rev <= 5 && !TARGET_MIPS16) +#define ISA_HAS_LWL_LWR (mips_isa_rev <= 5 && (!TARGET_MIPS16 || ISA_HAS_MIPS16E2)) #define ISA_HAS_IEEE_754_LEGACY (mips_isa_rev <= 5) diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 73c9acd484f..5ef8d99d99c 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -4488,10 +4488,12 @@ (unspec:GPR [(match_operand:BLK 1 "memory_operand" "m") (match_operand:QI 2 "memory_operand" "ZC")] UNSPEC_LOAD_LEFT))] - "!TARGET_MIPS16 && mips_mem_fits_mode_p (mode, operands[1])" + "(!TARGET_MIPS16 || ISA_HAS_MIPS16E2) + && mips_mem_fits_mode_p (mode, operands[1])" "l\t%0,%2" [(set_attr "move_type" "load") - (set_attr "mode" "")]) + (set_attr "mode" "") + (set_attr "extended_mips16" "yes")]) (define_insn "mov_r" [(set (match_operand:GPR 0 "register_operand" "=d") @@ -4499,17 +4501,20 @@ (match_operand:QI 2 "memory_operand" "ZC") (match_operand:GPR 3 "register_operand" "0")] UNSPEC_LOAD_RIGHT))] - "!TARGET_MIPS16 && mips_mem_fits_mode_p (mode, operands[1])" + "(!TARGET_MIPS16 || ISA_HAS_MIPS16E2) + && mips_mem_fits_mode_p (mode, operands[1])" "r\t%0,%2" [(set_attr "move_type" "load") - (set_attr "mode" "")]) + (set_attr "mode" "") + (set_attr "extended_mips16" "yes")]) (define_insn "mov_l" [(set (match_operand:BLK 0 "memory_operand" "=m") (unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ") (match_operand:QI 2 "memory_operand" "ZC")] UNSPEC_STORE_LEFT))] - "!TARGET_MIPS16 && mips_mem_fits_mode_p (mode, operands[0])" + "!TARGET_MIPS16 + && mips_mem_fits_mode_p (mode, operands[0])" "l\t%z1,%2" [(set_attr "move_type" "store") (set_attr "mode" "")]) @@ -4520,11 +4525,37 @@ (match_operand:QI 2 "memory_operand" "ZC") (match_dup 0)] UNSPEC_STORE_RIGHT))] - "!TARGET_MIPS16 && mips_mem_fits_mode_p (mode, operands[0])" + "!TARGET_MIPS16 + && mips_mem_fits_mode_p (mode, operands[0])" "r\t%z1,%2" [(set_attr "move_type" "store") (set_attr "mode" "")]) +(define_insn "mov_l_mips16e2" + [(set (match_operand:BLK 0 "memory_operand" "=m") + (unspec:BLK [(match_operand:GPR 1 "register_operand" "d") + (match_operand:QI 2 "memory_operand" "ZC")] + UNSPEC_STORE_LEFT))] + "TARGET_MIPS16 && ISA_HAS_MIPS16E2 + && mips_mem_fits_mode_p (mode, operands[0])" + "l\t%1,%2" + [(set_attr "move_type" "store") + (set_attr "mode" "") + (set_attr "extended_mips16" "yes")]) + +(define_insn "mov_r_mips16e2" + [(set (match_operand:BLK 0 "memory_operand" "+m") + (unspec:BLK [(match_operand:GPR 1 "register_operand" "d") + (match_operand:QI 2 "memory_operand" "ZC") + (match_dup 0)] + UNSPEC_STORE_RIGHT))] + "TARGET_MIPS16 && ISA_HAS_MIPS16E2 + && mips_mem_fits_mode_p (mode, operands[0])" + "r\t%1,%2" + [(set_attr "move_type" "store") + (set_attr "mode" "") + (set_attr "extended_mips16" "yes")]) + ;; Unaligned direct access (define_expand "movmisalign" [(set (match_operand:JOIN_MODE 0) diff --git a/gcc/testsuite/gcc.target/mips/mips16e2.c b/gcc/testsuite/gcc.target/mips/mips16e2.c index 780891b4056..166aa742268 100644 --- a/gcc/testsuite/gcc.target/mips/mips16e2.c +++ b/gcc/testsuite/gcc.target/mips/mips16e2.c @@ -122,3 +122,119 @@ test10 (int i) return i; } +/* Test 32bit unaligned load. */ + +/* { dg-final { scan-assembler "test11:.*\tlwl\t.*test11\n" } } */ +/* { dg-final { scan-assembler "test11:.*\tlwr\t.*test11\n" } } */ +struct node11 +{ + char c; + int i; +} __attribute__ ((packed)) obj11 __attribute__((aligned(1))); + +int +test11 (void) +{ + return obj11.i; +} + +/* Test 32bit unaligned load. */ + +/* { dg-final { scan-assembler "test12:.*\tlwl\t.*test12\n" } } */ +/* { dg-final { scan-assembler "test12:.*\tlwr\t.*test12\n" } } */ +struct node12 +{ + unsigned int i : 8; + unsigned int j : 32; +} __attribute__ ((packed)) obj12 __attribute__((aligned(16))); + +int +test12 (void) +{ + return obj12.j; +} + +/* Test 32bit unaligned store with non-zero constant */ + +/* { dg-final { scan-assembler "test13:.*\tswl\t.*test13\n" } } */ +/* { dg-final { scan-assembler "test13:.*\tswr\t.*test13\n" } } */ +struct node13 +{ + char c; + int i; +} __attribute__ ((packed)) obj13 __attribute__((aligned(1))); + +void +test13 (void) +{ + obj13.i = 1234; +} + +/* Test 32bit unaligned store with zero constant. */ + +/* { dg-final { scan-assembler "test14:.*\tswl\t.*test14\n" } } */ +/* { dg-final { scan-assembler "test14:.*\tswr\t.*test14\n" } } */ +/* { dg-final { scan-assembler-not "test14:.*\tswl\t\\\$0,.*test14\n" } } */ +/* { dg-final { scan-assembler-not "test14:.*\tswr\t\\\$0,.*test14\n" } } */ +struct node14 +{ + char c; + int i; +} __attribute__ ((packed)) obj14 __attribute__((aligned(1))); + +void +test14 (void) +{ + obj14.i = 0; +} + +/* Test 32bit unaligned store with non-constant. */ + +/* { dg-final { scan-assembler "test15:.*\tswl\t.*test15\n" } } */ +/* { dg-final { scan-assembler "test15:.*\tswr\t.*test15\n" } } */ +struct node15 +{ + char c; + int i; +} __attribute__ ((packed)) obj15 __attribute__((aligned(1))); + +int i15 = 1234; + +void +test15 (void) +{ + obj15.i = i15; +} + +/* Test 32bit unaligned store with non-constant */ + +/* { dg-final { scan-assembler "test16:.*\tswl\t.*test16\n" } } */ +/* { dg-final { scan-assembler "test16:.*\tswr\t.*test16\n" } } */ +struct node16 +{ + char c; + int i; +} __attribute__ ((packed)) obj16 __attribute__((aligned(1))); + +void +test16 (int i) +{ + obj16.i = i; +} + +/* Test 32bit unaligned store with non-constant. */ + +/* { dg-final { scan-assembler "test17:.*\tswl\t.*test17\n" } } */ +/* { dg-final { scan-assembler "test17:.*\tswr\t.*test17\n" } } */ +struct node17 +{ + unsigned int i : 8; + unsigned int j : 32; +} __attribute__ ((packed)) obj17 __attribute__((aligned(16))); + +void +test17 (int i) +{ + obj17.j = i; +} + -- 2.40.1