MIPS: R6: load/store can process unaligned address

MIPS release 6 requires the lw/ld/sw/sd can work with
unaligned address, while it can be implemented by
full hardware or trap&emulate.

Since it doesn't have to be fully done by hardware, we add a
pair of options -m(no-)unaligned-access. Kernels may need them.

gcc/ChangeLog:

	* config/mips/mips.h (ISA_HAS_UNALIGNED_ACCESS, STRICT_ALIGNMENT):
		R6 can unaligned access.
	* config/mips/mips.md (movmisalign<mode>): Likewise.
	* config/mips/mips.opt: add -m(no-)unaligned-access
	* doc/invoke.texi: Likewise.

gcc/testsuite/ChangeLog:

	* gcc.target/mips/mips.exp: add unaligned-access
	* gcc.target/mips/unaligned-2.c: New test.
	* gcc.target/mips/unaligned-3.c: New test.
This commit is contained in:
YunQiang Su 2021-10-11 06:42:39 -04:00 committed by YunQiang Su
parent 3d9e676793
commit 30a08286e6
7 changed files with 136 additions and 1 deletions

View file

@ -243,6 +243,10 @@ struct mips_cpu_info {
&& (mips_isa_rev >= 6 \
|| ISA_HAS_MSA))
/* ISA load/store instructions can handle unaligned address */
#define ISA_HAS_UNALIGNED_ACCESS (TARGET_UNALIGNED_ACCESS \
&& (mips_isa_rev >= 6))
/* The ISA compression flags that are currently in effect. */
#define TARGET_COMPRESSION (target_flags & (MASK_MIPS16 | MASK_MICROMIPS))
@ -1684,7 +1688,7 @@ FP_ASM_SPEC "\
(ISA_HAS_MSA ? BITS_PER_MSA_REG : LONG_DOUBLE_TYPE_SIZE)
/* All accesses must be aligned. */
#define STRICT_ALIGNMENT 1
#define STRICT_ALIGNMENT (!ISA_HAS_UNALIGNED_ACCESS)
/* Define this if you wish to imitate the way many other C compilers
handle alignment of bitfields and the structures that contain

View file

@ -4459,6 +4459,16 @@
[(set_attr "move_type" "store")
(set_attr "mode" "<MODE>")])
;; Unaligned direct access
(define_expand "movmisalign<mode>"
[(set (match_operand:JOIN_MODE 0)
(match_operand:JOIN_MODE 1))]
"ISA_HAS_UNALIGNED_ACCESS"
{
if (mips_legitimize_move (<MODE>mode, operands[0], operands[1]))
DONE;
})
;; An instruction to calculate the high part of a 64-bit SYMBOL_ABSOLUTE.
;; The required value is:
;;

View file

@ -404,6 +404,10 @@ mtune=
Target RejectNegative Joined Var(mips_tune_option) ToLower Enum(mips_arch_opt_value)
-mtune=PROCESSOR Optimize the output for PROCESSOR.
munaligned-access
Target Var(TARGET_UNALIGNED_ACCESS) Init(1)
Generate code with unaligned load store, valid for MIPS R6.
muninit-const-in-rodata
Target Var(TARGET_UNINIT_CONST_IN_RODATA)
Put uninitialized constants in ROM (needs -membedded-data).

View file

@ -1079,6 +1079,7 @@ Objective-C and Objective-C++ Dialects}.
-mcheck-zero-division -mno-check-zero-division @gol
-mdivide-traps -mdivide-breaks @gol
-mload-store-pairs -mno-load-store-pairs @gol
-munaligned-access -mno-unaligned-access @gol
-mmemcpy -mno-memcpy -mlong-calls -mno-long-calls @gol
-mmad -mno-mad -mimadd -mno-imadd -mfused-madd -mno-fused-madd -nocpp @gol
-mfix-24k -mno-fix-24k @gol
@ -25731,6 +25732,15 @@ instructions to enable load/store bonding. This option is enabled by
default but only takes effect when the selected architecture is known
to support bonding.
@item -munaligned-access
@itemx -mno-unaligned-access
@opindex munaligned-access
@opindex mno-unaligned-access
Enable (disable) direct unaligned access for MIPS Release 6.
MIPSr6 requires load/store unaligned-access support,
by hardware or trap&emulate.
So @option{-mno-unaligned-access} may be needed by kernel.
@item -mmemcpy
@itemx -mno-memcpy
@opindex mmemcpy

View file

@ -264,6 +264,7 @@ set mips_option_groups {
frame-header "-mframe-header-opt|-mno-frame-header-opt"
stack-protector "-fstack-protector"
stdlib "REQUIRES_STDLIB"
unaligned-access "-m(no-|)unaligned-access"
}
for { set option 0 } { $option < 32 } { incr option } {

View file

@ -0,0 +1,53 @@
/* { dg-options "isa_rev>=6 -mgp64" } */
/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
/* { dg-final { scan-assembler-not "\tsb\t" } } */
/* { dg-final { scan-assembler-not "\tsh\t" } } */
/* { dg-final { scan-assembler-not "\tlb\t" } } */
/* { dg-final { scan-assembler-not "\tlh\t" } } */
/* { dg-final { scan-assembler-not "\tswl\t" } } */
/* { dg-final { scan-assembler-not "\tswr\t" } } */
/* { dg-final { scan-assembler-not "\tlwl\t" } } */
/* { dg-final { scan-assembler-not "\tlwr\t" } } */
/* { dg-final { scan-assembler-not "\tsdl\t" } } */
/* { dg-final { scan-assembler-not "\tsdr\t" } } */
/* { dg-final { scan-assembler-not "\tldl\t" } } */
/* { dg-final { scan-assembler-not "\tldr\t" } } */
/* { dg-final { scan-assembler-times "\tsw\t" 1 } } */
/* { dg-final { scan-assembler-times "\tlw\t" 1 } } */
/* { dg-final { scan-assembler-times "\tsd\t" 1 } } */
/* { dg-final { scan-assembler-times "\tld\t" 1 } } */
/* { dg-final { scan-assembler-not "\tnop" } } */
/* Test to make sure we produce the unaligned load/store for
both 64bit and 32bits sized accesses. */
struct s
{
char c;
int i;
long long l;
} __attribute__ ((packed)) s __attribute__((aligned(1) ));
NOMIPS16 void
sd (long long l)
{
s.l = l;
}
NOMIPS16 long long
ld ()
{
return s.l;
}
NOMIPS16 void
sw (int i)
{
s.i = i;
}
NOMIPS16 int
lw ()
{
return s.i;
}

View file

@ -0,0 +1,53 @@
/* { dg-options "isa_rev>=6 -mgp64 -mno-unaligned-access" } */
/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
/* { dg-final { scan-assembler-times "\tsb\t" 12 } } */
/* { dg-final { scan-assembler-times "\tlbu\t" 12 } } */
/* { dg-final { scan-assembler-not "\tsh\t" } } */
/* { dg-final { scan-assembler-not "\tlh\t" } } */
/* { dg-final { scan-assembler-not "\tsw\t" } } */
/* { dg-final { scan-assembler-not "\tlw\t" } } */
/* { dg-final { scan-assembler-not "\tsd\t" } } */
/* { dg-final { scan-assembler-not "\tld\t" } } */
/* { dg-final { scan-assembler-not "\tswl\t" } } */
/* { dg-final { scan-assembler-not "\tswr\t" } } */
/* { dg-final { scan-assembler-not "\tlwl\t" } } */
/* { dg-final { scan-assembler-not "\tlwr\t" } } */
/* { dg-final { scan-assembler-not "\tsdl\t" } } */
/* { dg-final { scan-assembler-not "\tsdr\t" } } */
/* { dg-final { scan-assembler-not "\tldl\t" } } */
/* { dg-final { scan-assembler-not "\tldr\t" } } */
/* { dg-final { scan-assembler-not "\tnop" } } */
/* Test to make sure we produce the unaligned load/store for
both 64bit and 32bits sized accesses. */
struct s
{
char c;
int i;
long long l;
} __attribute__ ((packed)) s __attribute__((aligned(1) ));
NOMIPS16 void
sd (long long l)
{
s.l = l;
}
NOMIPS16 long long
ld ()
{
return s.l;
}
NOMIPS16 void
sw (int i)
{
s.i = i;
}
NOMIPS16 int
lw ()
{
return s.i;
}