diff mbox series

[FFmpeg-devel,v2,1/4] ffbuild: Refine MIPS handling

Message ID 20200602141507.11151-2-jiaxun.yang@flygoat.com
State Superseded
Headers show
Series MIPS MSA & MMI Runtime detection support
Related show

Checks

Context Check Description
andriy/default pending
andriy/make success Make finished
andriy/make_fate success Make fate finished

Commit Message

Jiaxun Yang June 2, 2020, 2:15 p.m. UTC
To enable runtime detection for MIPS, we need to refine ffbuild
part to support buildding these feature together.

Firstly, we fixed configure, let it probe native ability of toolchain
to decide wether a feature can to be enabled, also clearly marked
the conflictions between loongson2 & loongson3 and Release 6 & rest.

Secondly, we compile MMI and MSA C sources with their own flags to ensure
their flags won't pollute the whole program and generate illegal code.

Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 configure                | 179 +++++++++++++++++++++++----------------
 ffbuild/common.mak       |  10 ++-
 libavcodec/mips/Makefile |   3 +-
 3 files changed, 117 insertions(+), 75 deletions(-)

Comments

Shiyou Yin June 4, 2020, 7:37 a.m. UTC | #1
For your convenience, I add the previous comments into this patch.

>-----Original Message-----
>From: ffmpeg-devel-bounces@ffmpeg.org [mailto:ffmpeg-devel-bounces@ffmpeg.org] On Behalf Of
>Jiaxun Yang
>Sent: Tuesday, June 2, 2020 10:15 PM
>To: ffmpeg-devel@ffmpeg.org
>Cc: yinshiyou@loongson.cn; Jiaxun Yang
>Subject: [FFmpeg-devel] [PATCH v2 1/4] ffbuild: Refine MIPS handling
>
>To enable runtime detection for MIPS, we need to refine ffbuild
>part to support buildding these feature together.
>
>Firstly, we fixed configure, let it probe native ability of toolchain
>to decide wether a feature can to be enabled, also clearly marked
>the conflictions between loongson2 & loongson3 and Release 6 & rest.
>
>Secondly, we compile MMI and MSA C sources with their own flags to ensure
>their flags won't pollute the whole program and generate illegal code.
>
>Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>---
> configure                | 179 +++++++++++++++++++++++----------------
> ffbuild/common.mak       |  10 ++-
> libavcodec/mips/Makefile |   3 +-
> 3 files changed, 117 insertions(+), 75 deletions(-)
>
>diff --git a/configure b/configure
>index f97cad0298..8dc3874642 100755
>--- a/configure
>+++ b/configure
>@@ -1113,6 +1113,26 @@ void foo(void){ __asm__ volatile($code); }
> EOF
> }
>
>+check_extra_inline_asm_flags(){
>+    log check_extra_inline_asm_flags "$@"
>+    name="$1"
>+    extra=$2
>+    code="$3"
>+    flags=''
>+    shift 3
>+    while [ "$1" != "" ]; do
>+      append flags $1
>+      shift
>+    done;
>+    disable $name
>+    cat > $TMPC <<EOF
>+void foo(void){ __asm__ volatile($code); }
>+EOF
>+    log_file $TMPC
>+    test_cmd $cc $CPPFLAGS $CFLAGS $flags "$@" $CC_C $(cc_o $TMPO) $TMPC &&
>+    enable $name && append $extra "$flags"
>+}
>+

You can use check_inline_asm. e.g. 
enabled msa && check_inline_asm msa '"addvi.b $w0, $w1, 1"' '-mmsa' && append MSAFLAGS '-mmsa'
enabled mmi && check_inline_asm mmi '"punpcklhw $f0, $f0, $f0"' "-mloongson-mmi" && append MMIFLAGS '-mloongson-mmi'
enabled loongson3 && check_inline_asm loongson3 '"gsldxc1 $f0, 0($2, $3)"' '-mloongson-ext' && append MMIFLAGS '-mloongson-ext'

> check_inline_asm_flags(){
>     log check_inline_asm_flags "$@"
>     name="$1"
>@@ -2551,7 +2571,7 @@ mips64r6_deps="mips"
> mipsfpu_deps="mips"
> mipsdsp_deps="mips"
> mipsdspr2_deps="mips"
>-mmi_deps="mips"
>+mmi_deps_any="loongson2 loongson3"
> msa_deps="mipsfpu"
> msa2_deps="msa"
>
>@@ -4999,29 +5019,57 @@ elif enabled bfin; then
>
> elif enabled mips; then

In this block, you only need to disable the unsupported extensions for each cpu case,
for all extensions in ARCH_EXT_LIST will be enabled by default.

>
>-    cpuflags="-march=$cpu"
>-
>     if [ "$cpu" != "generic" ]; then
>-        disable mips32r2
>-        disable mips32r5
>-        disable mips64r2
>-        disable mips32r6
>-        disable mips64r6
>-        disable loongson2
>-        disable loongson3
>+        # DSP is disabled by deafult as they can't be detected at runtime
>+        disable mipsdsp
>+        disable mipsdspr2
>+
>+        cpuflags="-march=$cpu"
>
>         case $cpu in
>-            24kc|24kf*|24kec|34kc|1004kc|24kef*|34kf*|1004kf*|74kc|74kf)
>+            # General ISA levels
>+            mips1|mips3)
>+                disable msa
>+            ;;
>+            mips32r2)
>                 enable mips32r2

If you havn't disable it at the beginning of this if block, you needn’t enable it explicitly here.

>+            ;;
>+            mips32r5)
>+                enable mips32r5
>+            ;;
>+            mips64r2|mips64r5)
>+                enable mips64r2
>+            ;;
>+            # Cores from MIPS(MTI)
>+            24kc)
>+                disable mipsfpu
>+            ;;
>+            24kf*|24kec|34kc|74Kc|1004kc)
>+                disable mmi
>                 disable msa
>             ;;
>-            p5600|i6400|p6600)
>-                disable mipsdsp
>-                disable mipsdspr2
>+            24kef*|34kf*|1004kf*)
>+                disable mmi
>+                disable msa
>+                enable mipsdsp
>+            ;;
>+            p5600)
>+                disable mmi
>+                enable mips32r5
>+                check_cflags "-mtune=p5600" && check_cflags "-msched-weight -mload-store-pairs
>-funroll-loops"
>+            ;;
>+            i6400)
>+                disable mmi
>+                enable mips64r6
>+                check_cflags "-mtune=i6400 -mabi=64" && check_cflags "-msched-weight
>-mload-store-pairs -funroll-loops" && check_ldflags "-mabi=64"
>+            ;;
>+            p6600)
>+                disable mmi
>+                enable mips64r6
>+                check_cflags "-mtune=p6600 -mabi=64" && check_cflags "-msched-weight
>-mload-store-pairs -funroll-loops" && check_ldflags "-mabi=64"
>             ;;
>+            # Cores from Loongson
>             loongson*)
>-                enable loongson2
>-                enable loongson3
>                 enable local_aligned
>                 enable simd_align_16
>                 enable fast_64bit
>@@ -5029,8 +5077,6 @@ elif enabled mips; then
>                 enable fast_cmov
>                 enable fast_unaligned
>                 disable aligned_stack
>-                disable mipsdsp
>-                disable mipsdspr2
>                 # When gcc version less than 5.3.0, add -fno-expensive-optimizations flag.
>                 if [ $cc == gcc ]; then
>                     gcc_version=$(gcc -dumpversion)
>@@ -5042,62 +5088,26 @@ elif enabled mips; then
>                 fi
>                 case $cpu in
>                     loongson3*)
>+                        enable loongson3
>+                        enable mips64r2
>                         cpuflags="-march=loongson3a -mhard-float $expensive_optimization_flag"
>                     ;;
>                     loongson2e)
>+                        enable loongson2
>                         cpuflags="-march=loongson2e -mhard-float $expensive_optimization_flag"
>                     ;;
>                     loongson2f)
>+                        enable loongson2
>                         cpuflags="-march=loongson2f -mhard-float $expensive_optimization_flag"
>                     ;;
>                 esac
>             ;;
>             *)
>-                # Unknown CPU. Disable everything.
>-                warn "unknown CPU. Disabling all MIPS optimizations."
>-                disable mipsfpu
>-                disable mipsdsp
>-                disable mipsdspr2
>-                disable msa
>-                disable mmi
>+                warn "unknown MIPS CPU"
>             ;;
>         esac
>
>-        case $cpu in
>-            24kc)
>-                disable mipsfpu
>-                disable mipsdsp
>-                disable mipsdspr2
>-            ;;
>-            24kf*)
>-                disable mipsdsp
>-                disable mipsdspr2
>-            ;;
>-            24kec|34kc|1004kc)
>-                disable mipsfpu
>-                disable mipsdspr2
>-            ;;
>-            24kef*|34kf*|1004kf*)
>-                disable mipsdspr2
>-            ;;
>-            74kc)
>-                disable mipsfpu
>-            ;;
>-            p5600)
>-                enable mips32r5
>-                check_cflags "-mtune=p5600" && check_cflags "-msched-weight -mload-store-pairs
>-funroll-loops"
>-            ;;
>-            i6400)
>-                enable mips64r6
>-                check_cflags "-mtune=i6400 -mabi=64" && check_cflags "-msched-weight
>-mload-store-pairs -funroll-loops" && check_ldflags "-mabi=64"
>-            ;;
>-            p6600)
>-                enable mips64r6
>-                check_cflags "-mtune=p6600 -mabi=64" && check_cflags "-msched-weight
>-mload-store-pairs -funroll-loops" && check_ldflags "-mabi=64"
>-            ;;
>-        esac
>     else
>-        # We do not disable anything. Is up to the user to disable the unwanted features.

I suggest to keep and adjust this note, in case of DSP.

>         warn 'generic cpu selected'
>     fi
>
>@@ -5844,28 +5854,49 @@ EOF
>
> elif enabled mips; then
>
>-    enabled loongson2 && check_inline_asm loongson2 '"dmult.g $8, $9, $10"'
>-    enabled loongson3 && check_inline_asm loongson3 '"gsldxc1 $f0, 0($2, $3)"'
>-    enabled mmi && check_inline_asm mmi '"punpcklhw $f0, $f0, $f0"'
>
>-    # Enable minimum ISA based on selected options
>+    # Check toolchain ISA level
>     if enabled mips64; then
>-        enabled mips64r6 && check_inline_asm_flags mips64r6 '"dlsa $0, $0, $0, 1"' '-mips64r6'
>-        enabled mips64r2 && check_inline_asm_flags mips64r2 '"dext $0, $0, 0, 1"' '-mips64r2'
>-        disabled mips64r6 && disabled mips64r2 && check_inline_asm_flags mips64r1 '"daddi $0, $0,
>0"' '-mips64'
>+        enabled mips64r6 && check_inline_asm mips64r6 '"dlsa $0, $0, $0, 1"' &&
>+            disable mips64r2
>+        enabled mips64r2 && check_inline_asm mips64r2 '"dext $0, $0, 0, 1"'
>+
>+        disable mips32r6 && disable mips32r5 && disable mips32r2
>     else
>-        enabled mips32r6 && check_inline_asm_flags mips32r6 '"aui $0, $0, 0"' '-mips32r6'
>-        enabled mips32r5 && check_inline_asm_flags mips32r5 '"eretnc"' '-mips32r5'
>-        enabled mips32r2 && check_inline_asm_flags mips32r2 '"ext $0, $0, 0, 1"' '-mips32r2'
>-        disabled mips32r6 && disabled mips32r5 && disabled mips32r2 && check_inline_asm_flags
>mips32r1 '"addi $0, $0, 0"' '-mips32'
>+        enabled mips32r6 && check_inline_asm mips32r6 '"aui $0, $0, 0"' &&
>+            disable mips32r5 && disable mips32r2
>+        enabled mips32r5 && check_inline_asm mips32r5 '"eretnc"'
>+        enabled mips32r2 && check_inline_asm mips32r2 '"ext $0, $0, 0, 1"'
>+
>+        disable mips64r6 && disable mips64r5 && disable mips64r2
>     fi
>
>-    enabled mipsfpu && check_inline_asm_flags mipsfpu '"cvt.d.l $f0, $f2"' '-mhard-float'
>+    enabled mipsfpu && check_inline_asm mipsfpu '"cvt.d.l $f0, $f2"'
>     enabled mipsfpu && (enabled mips32r5 || enabled mips32r6 || enabled mips64r6) &&
>check_inline_asm_flags mipsfpu '"cvt.d.l $f0, $f1"' '-mfp64'
>-    enabled mipsfpu && enabled msa && check_inline_asm_flags msa '"addvi.b $w0, $w1, 1"' '-mmsa'
>&& check_headers msa.h || disable msa
>+

Don't forget msa_deps=mipsfpu.

>     enabled mipsdsp && check_inline_asm_flags mipsdsp '"addu.qb $t0, $t1, $t2"' '-mdsp'
>     enabled mipsdspr2 && check_inline_asm_flags mipsdspr2 '"absq_s.qb $t0, $t1"' '-mdspr2'
>-    enabled msa && enabled msa2 && check_inline_asm_flags msa2 '"nxbits.any.b $w0, $w0"'
>'-mmsa2' && check_headers msa2.h || disable msa2
>+
>+    # MSA and MSA2 can be detected at runtime so we supply extra flags here
>+    enabled msa && check_extra_inline_asm_flags msa MSAFLAGS '"addvi.b $w0, $w1, 1"' '-mmsa'
>+    enabled msa && enabled msa2 && check_extra_inline_asm_flags msa2 MSAFLAGS '"nxbits.any.b
>$w0, $w0"' '-mmsa2'
>+

You can use check_inline_asm:
+    enabled msa && check_inline_asm msa '"addvi.b $w0, $w1, 1"' '-mmsa'
+               && append MSAFLAGS '-mmsa'
+    enabled msa && enabled msa2 && check_inline_asm msa2 '"nxbits.any.b $w0, $w0"' '-mmsa2'
+               && append MSAFLAGS '-mmsa2'

>+    # loongson2 have no switch cflag so we can only probe toolchain ability
>+    enabled loongson2 && check_inline_asm loongson2 '"dmult.g $8, $9, $10"'
>+    if enabled loongson2 ; then
>+        disable loongson3
>+    fi
>+
>+    # loongson3 can be treated as a part of MMI
>+    enabled loongson3 && check_extra_inline_asm_flags loongson3 MMIFLAGS '"gsldxc1 $f0, 0($2,
>$3)"' '-mloongson-ext'
>+
>+    # MMI must come together with loongson2 or loongson3
>+    if disabled loongson2 && disabled loongson3; then
>+        disable mmi
>+    fi
>+
>+    # MMI can be detected at runtime too
>+    enabled mmi && check_extra_inline_asm_flags mmi MMIFLAGS '"punpcklhw $f0, $f0, $f0"'
>'-mloongson-mmi'
>

Suggest to use check_inline_asm for loongson3 and mmi too,
For mmi, explicitly append "-mloongson-mmi -mloongson-ext" to MMIFLAGS.
Just in case of cpu=loongson2, '-mloongson-ext ' is also needed.

+    # loongson3 can be treated as a part of MMI
+    enabled loongson3 && check_inline_asm loongson3 '"gsldxc1 $f0, 0($2, $3)"' '-mloongson-ext'
+                    && append MMIFLAGS '-mloongson-ext'
+
+    # MMI must come together with loongson2 or loongson3
+    if disabled loongson2 && disabled loongson3; then
+        disable mmi
+    fi
+
+    # MMI can be detected at runtime too
+    enabled mmi && check_ inline_asm mmi '"punpcklhw $f0, $f0, $f0"' '-mloongson-mmi'
+               && append MMIFLAGS '-mloongson-mmi'

>     if enabled bigendian && enabled msa; then
>         disable msa
>@@ -7439,6 +7470,8 @@ LDSOFLAGS=$LDSOFLAGS
> SHFLAGS=$(echo $($ldflags_filter $SHFLAGS))
> ASMSTRIPFLAGS=$ASMSTRIPFLAGS
> X86ASMFLAGS=$X86ASMFLAGS
>+MSAFLAGS=$MSAFLAGS
>+MMIFLAGS=$MMIFLAGS
> BUILDSUF=$build_suffix
> PROGSSUF=$progs_suffix
> FULLNAME=$FULLNAME
>diff --git a/ffbuild/common.mak b/ffbuild/common.mak
>index a60d27c9bd..6b95a17fbb 100644
>--- a/ffbuild/common.mak
>+++ b/ffbuild/common.mak
>@@ -44,7 +44,7 @@ LDFLAGS    := $(ALLFFLIBS:%=$(LD_PATH)lib%) $(LDFLAGS)
>
> define COMPILE
>        $(call $(1)DEP,$(1))
>-       $($(1)) $($(1)FLAGS) $($(1)_DEPFLAGS) $($(1)_C) $($(1)_O) $(patsubst
>$(SRC_PATH)/%,$(SRC_LINK)/%,$<)
>+       $($(1)) $($(1)FLAGS) $($(1)_DEPFLAGS) $($(1)_C) $($(1)_O) $($(2)) $(patsubst
>$(SRC_PATH)/%,$(SRC_LINK)/%,$<)
> endef
>
> COMPILE_C = $(call COMPILE,CC)
>@@ -54,6 +54,14 @@ COMPILE_M = $(call COMPILE,OBJCC)
> COMPILE_X86ASM = $(call COMPILE,X86ASM)
> COMPILE_HOSTC = $(call COMPILE,HOSTCC)
> COMPILE_NVCC = $(call COMPILE,NVCC)
>+COMPILE_MMI = $(call COMPILE,CC,MMIFLAGS)
>+COMPILE_MSA = $(call COMPILE,CC,MSAFLAGS)
>+
>+%_mmi.o: %_mmi.c
>+	$(COMPILE_MMI)
>+
>+%_msa.o: %_msa.c
>+	$(COMPILE_MSA)
>
> %.o: %.c
> 	$(COMPILE_C)
>diff --git a/libavcodec/mips/Makefile b/libavcodec/mips/Makefile
>index b4993f6e76..2be4d9b8a2 100644
>--- a/libavcodec/mips/Makefile
>+++ b/libavcodec/mips/Makefile
>@@ -71,6 +71,8 @@ MSA-OBJS-$(CONFIG_IDCTDSP)                += mips/idctdsp_msa.o
>\
> MSA-OBJS-$(CONFIG_MPEGVIDEO)              += mips/mpegvideo_msa.o
> MSA-OBJS-$(CONFIG_MPEGVIDEOENC)           += mips/mpegvideoencdsp_msa.o
> MSA-OBJS-$(CONFIG_ME_CMP)                 += mips/me_cmp_msa.o
>+MSA-OBJS-$(CONFIG_VC1_DECODER)            += mips/vc1dsp_msa.o
>+
> MMI-OBJS                                  += mips/constants.o
> MMI-OBJS-$(CONFIG_H264DSP)                += mips/h264dsp_mmi.o
> MMI-OBJS-$(CONFIG_H264CHROMA)             += mips/h264chroma_mmi.o
>@@ -89,4 +91,3 @@ MMI-OBJS-$(CONFIG_WMV2DSP)                += mips/wmv2dsp_mmi.o
> MMI-OBJS-$(CONFIG_HEVC_DECODER)           += mips/hevcdsp_mmi.o
> MMI-OBJS-$(CONFIG_VP3DSP)                 += mips/vp3dsp_idct_mmi.o
> MMI-OBJS-$(CONFIG_VP9_DECODER)            += mips/vp9_mc_mmi.o
>-MSA-OBJS-$(CONFIG_VC1_DECODER)            += mips/vc1dsp_msa.o
>--
>2.26.2
>
>
>_______________________________________________
>ffmpeg-devel mailing list
>ffmpeg-devel@ffmpeg.org
>https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
>To unsubscribe, visit link above, or email
>ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
diff mbox series

Patch

diff --git a/configure b/configure
index f97cad0298..8dc3874642 100755
--- a/configure
+++ b/configure
@@ -1113,6 +1113,26 @@  void foo(void){ __asm__ volatile($code); }
 EOF
 }
 
+check_extra_inline_asm_flags(){
+    log check_extra_inline_asm_flags "$@"
+    name="$1"
+    extra=$2
+    code="$3"
+    flags=''
+    shift 3
+    while [ "$1" != "" ]; do
+      append flags $1
+      shift
+    done;
+    disable $name
+    cat > $TMPC <<EOF
+void foo(void){ __asm__ volatile($code); }
+EOF
+    log_file $TMPC
+    test_cmd $cc $CPPFLAGS $CFLAGS $flags "$@" $CC_C $(cc_o $TMPO) $TMPC &&
+    enable $name && append $extra "$flags"
+}
+
 check_inline_asm_flags(){
     log check_inline_asm_flags "$@"
     name="$1"
@@ -2551,7 +2571,7 @@  mips64r6_deps="mips"
 mipsfpu_deps="mips"
 mipsdsp_deps="mips"
 mipsdspr2_deps="mips"
-mmi_deps="mips"
+mmi_deps_any="loongson2 loongson3"
 msa_deps="mipsfpu"
 msa2_deps="msa"
 
@@ -4999,29 +5019,57 @@  elif enabled bfin; then
 
 elif enabled mips; then
 
-    cpuflags="-march=$cpu"
-
     if [ "$cpu" != "generic" ]; then
-        disable mips32r2
-        disable mips32r5
-        disable mips64r2
-        disable mips32r6
-        disable mips64r6
-        disable loongson2
-        disable loongson3
+        # DSP is disabled by deafult as they can't be detected at runtime
+        disable mipsdsp
+        disable mipsdspr2
+
+        cpuflags="-march=$cpu"
 
         case $cpu in
-            24kc|24kf*|24kec|34kc|1004kc|24kef*|34kf*|1004kf*|74kc|74kf)
+            # General ISA levels
+            mips1|mips3)
+                disable msa
+            ;;
+            mips32r2)
                 enable mips32r2
+            ;;
+            mips32r5)
+                enable mips32r5
+            ;;
+            mips64r2|mips64r5)
+                enable mips64r2
+            ;;
+            # Cores from MIPS(MTI)
+            24kc)
+                disable mipsfpu
+            ;;
+            24kf*|24kec|34kc|74Kc|1004kc)
+                disable mmi
                 disable msa
             ;;
-            p5600|i6400|p6600)
-                disable mipsdsp
-                disable mipsdspr2
+            24kef*|34kf*|1004kf*)
+                disable mmi
+                disable msa
+                enable mipsdsp
+            ;;
+            p5600)
+                disable mmi
+                enable mips32r5
+                check_cflags "-mtune=p5600" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops"
+            ;;
+            i6400)
+                disable mmi
+                enable mips64r6
+                check_cflags "-mtune=i6400 -mabi=64" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" && check_ldflags "-mabi=64"
+            ;;
+            p6600)
+                disable mmi
+                enable mips64r6
+                check_cflags "-mtune=p6600 -mabi=64" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" && check_ldflags "-mabi=64"
             ;;
+            # Cores from Loongson
             loongson*)
-                enable loongson2
-                enable loongson3
                 enable local_aligned
                 enable simd_align_16
                 enable fast_64bit
@@ -5029,8 +5077,6 @@  elif enabled mips; then
                 enable fast_cmov
                 enable fast_unaligned
                 disable aligned_stack
-                disable mipsdsp
-                disable mipsdspr2
                 # When gcc version less than 5.3.0, add -fno-expensive-optimizations flag.
                 if [ $cc == gcc ]; then
                     gcc_version=$(gcc -dumpversion)
@@ -5042,62 +5088,26 @@  elif enabled mips; then
                 fi
                 case $cpu in
                     loongson3*)
+                        enable loongson3
+                        enable mips64r2
                         cpuflags="-march=loongson3a -mhard-float $expensive_optimization_flag"
                     ;;
                     loongson2e)
+                        enable loongson2
                         cpuflags="-march=loongson2e -mhard-float $expensive_optimization_flag"
                     ;;
                     loongson2f)
+                        enable loongson2
                         cpuflags="-march=loongson2f -mhard-float $expensive_optimization_flag"
                     ;;
                 esac
             ;;
             *)
-                # Unknown CPU. Disable everything.
-                warn "unknown CPU. Disabling all MIPS optimizations."
-                disable mipsfpu
-                disable mipsdsp
-                disable mipsdspr2
-                disable msa
-                disable mmi
+                warn "unknown MIPS CPU"
             ;;
         esac
 
-        case $cpu in
-            24kc)
-                disable mipsfpu
-                disable mipsdsp
-                disable mipsdspr2
-            ;;
-            24kf*)
-                disable mipsdsp
-                disable mipsdspr2
-            ;;
-            24kec|34kc|1004kc)
-                disable mipsfpu
-                disable mipsdspr2
-            ;;
-            24kef*|34kf*|1004kf*)
-                disable mipsdspr2
-            ;;
-            74kc)
-                disable mipsfpu
-            ;;
-            p5600)
-                enable mips32r5
-                check_cflags "-mtune=p5600" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops"
-            ;;
-            i6400)
-                enable mips64r6
-                check_cflags "-mtune=i6400 -mabi=64" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" && check_ldflags "-mabi=64"
-            ;;
-            p6600)
-                enable mips64r6
-                check_cflags "-mtune=p6600 -mabi=64" && check_cflags "-msched-weight -mload-store-pairs -funroll-loops" && check_ldflags "-mabi=64"
-            ;;
-        esac
     else
-        # We do not disable anything. Is up to the user to disable the unwanted features.
         warn 'generic cpu selected'
     fi
 
@@ -5844,28 +5854,49 @@  EOF
 
 elif enabled mips; then
 
-    enabled loongson2 && check_inline_asm loongson2 '"dmult.g $8, $9, $10"'
-    enabled loongson3 && check_inline_asm loongson3 '"gsldxc1 $f0, 0($2, $3)"'
-    enabled mmi && check_inline_asm mmi '"punpcklhw $f0, $f0, $f0"'
 
-    # Enable minimum ISA based on selected options
+    # Check toolchain ISA level
     if enabled mips64; then
-        enabled mips64r6 && check_inline_asm_flags mips64r6 '"dlsa $0, $0, $0, 1"' '-mips64r6'
-        enabled mips64r2 && check_inline_asm_flags mips64r2 '"dext $0, $0, 0, 1"' '-mips64r2'
-        disabled mips64r6 && disabled mips64r2 && check_inline_asm_flags mips64r1 '"daddi $0, $0, 0"' '-mips64'
+        enabled mips64r6 && check_inline_asm mips64r6 '"dlsa $0, $0, $0, 1"' &&
+            disable mips64r2
+        enabled mips64r2 && check_inline_asm mips64r2 '"dext $0, $0, 0, 1"'
+
+        disable mips32r6 && disable mips32r5 && disable mips32r2
     else
-        enabled mips32r6 && check_inline_asm_flags mips32r6 '"aui $0, $0, 0"' '-mips32r6'
-        enabled mips32r5 && check_inline_asm_flags mips32r5 '"eretnc"' '-mips32r5'
-        enabled mips32r2 && check_inline_asm_flags mips32r2 '"ext $0, $0, 0, 1"' '-mips32r2'
-        disabled mips32r6 && disabled mips32r5 && disabled mips32r2 && check_inline_asm_flags mips32r1 '"addi $0, $0, 0"' '-mips32'
+        enabled mips32r6 && check_inline_asm mips32r6 '"aui $0, $0, 0"' &&
+            disable mips32r5 && disable mips32r2
+        enabled mips32r5 && check_inline_asm mips32r5 '"eretnc"'
+        enabled mips32r2 && check_inline_asm mips32r2 '"ext $0, $0, 0, 1"'
+
+        disable mips64r6 && disable mips64r5 && disable mips64r2
     fi
 
-    enabled mipsfpu && check_inline_asm_flags mipsfpu '"cvt.d.l $f0, $f2"' '-mhard-float'
+    enabled mipsfpu && check_inline_asm mipsfpu '"cvt.d.l $f0, $f2"'
     enabled mipsfpu && (enabled mips32r5 || enabled mips32r6 || enabled mips64r6) && check_inline_asm_flags mipsfpu '"cvt.d.l $f0, $f1"' '-mfp64'
-    enabled mipsfpu && enabled msa && check_inline_asm_flags msa '"addvi.b $w0, $w1, 1"' '-mmsa' && check_headers msa.h || disable msa
+
     enabled mipsdsp && check_inline_asm_flags mipsdsp '"addu.qb $t0, $t1, $t2"' '-mdsp'
     enabled mipsdspr2 && check_inline_asm_flags mipsdspr2 '"absq_s.qb $t0, $t1"' '-mdspr2'
-    enabled msa && enabled msa2 && check_inline_asm_flags msa2 '"nxbits.any.b $w0, $w0"' '-mmsa2' && check_headers msa2.h || disable msa2
+
+    # MSA and MSA2 can be detected at runtime so we supply extra flags here
+    enabled msa && check_extra_inline_asm_flags msa MSAFLAGS '"addvi.b $w0, $w1, 1"' '-mmsa'
+    enabled msa && enabled msa2 && check_extra_inline_asm_flags msa2 MSAFLAGS '"nxbits.any.b $w0, $w0"' '-mmsa2'
+
+    # loongson2 have no switch cflag so we can only probe toolchain ability
+    enabled loongson2 && check_inline_asm loongson2 '"dmult.g $8, $9, $10"'
+    if enabled loongson2 ; then
+        disable loongson3
+    fi
+
+    # loongson3 can be treated as a part of MMI
+    enabled loongson3 && check_extra_inline_asm_flags loongson3 MMIFLAGS '"gsldxc1 $f0, 0($2, $3)"' '-mloongson-ext'
+
+    # MMI must come together with loongson2 or loongson3
+    if disabled loongson2 && disabled loongson3; then
+        disable mmi
+    fi
+
+    # MMI can be detected at runtime too
+    enabled mmi && check_extra_inline_asm_flags mmi MMIFLAGS '"punpcklhw $f0, $f0, $f0"' '-mloongson-mmi'
 
     if enabled bigendian && enabled msa; then
         disable msa
@@ -7439,6 +7470,8 @@  LDSOFLAGS=$LDSOFLAGS
 SHFLAGS=$(echo $($ldflags_filter $SHFLAGS))
 ASMSTRIPFLAGS=$ASMSTRIPFLAGS
 X86ASMFLAGS=$X86ASMFLAGS
+MSAFLAGS=$MSAFLAGS
+MMIFLAGS=$MMIFLAGS
 BUILDSUF=$build_suffix
 PROGSSUF=$progs_suffix
 FULLNAME=$FULLNAME
diff --git a/ffbuild/common.mak b/ffbuild/common.mak
index a60d27c9bd..6b95a17fbb 100644
--- a/ffbuild/common.mak
+++ b/ffbuild/common.mak
@@ -44,7 +44,7 @@  LDFLAGS    := $(ALLFFLIBS:%=$(LD_PATH)lib%) $(LDFLAGS)
 
 define COMPILE
        $(call $(1)DEP,$(1))
-       $($(1)) $($(1)FLAGS) $($(1)_DEPFLAGS) $($(1)_C) $($(1)_O) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<)
+       $($(1)) $($(1)FLAGS) $($(1)_DEPFLAGS) $($(1)_C) $($(1)_O) $($(2)) $(patsubst $(SRC_PATH)/%,$(SRC_LINK)/%,$<)
 endef
 
 COMPILE_C = $(call COMPILE,CC)
@@ -54,6 +54,14 @@  COMPILE_M = $(call COMPILE,OBJCC)
 COMPILE_X86ASM = $(call COMPILE,X86ASM)
 COMPILE_HOSTC = $(call COMPILE,HOSTCC)
 COMPILE_NVCC = $(call COMPILE,NVCC)
+COMPILE_MMI = $(call COMPILE,CC,MMIFLAGS)
+COMPILE_MSA = $(call COMPILE,CC,MSAFLAGS)
+
+%_mmi.o: %_mmi.c
+	$(COMPILE_MMI)
+
+%_msa.o: %_msa.c
+	$(COMPILE_MSA)
 
 %.o: %.c
 	$(COMPILE_C)
diff --git a/libavcodec/mips/Makefile b/libavcodec/mips/Makefile
index b4993f6e76..2be4d9b8a2 100644
--- a/libavcodec/mips/Makefile
+++ b/libavcodec/mips/Makefile
@@ -71,6 +71,8 @@  MSA-OBJS-$(CONFIG_IDCTDSP)                += mips/idctdsp_msa.o           \
 MSA-OBJS-$(CONFIG_MPEGVIDEO)              += mips/mpegvideo_msa.o
 MSA-OBJS-$(CONFIG_MPEGVIDEOENC)           += mips/mpegvideoencdsp_msa.o
 MSA-OBJS-$(CONFIG_ME_CMP)                 += mips/me_cmp_msa.o
+MSA-OBJS-$(CONFIG_VC1_DECODER)            += mips/vc1dsp_msa.o
+
 MMI-OBJS                                  += mips/constants.o
 MMI-OBJS-$(CONFIG_H264DSP)                += mips/h264dsp_mmi.o
 MMI-OBJS-$(CONFIG_H264CHROMA)             += mips/h264chroma_mmi.o
@@ -89,4 +91,3 @@  MMI-OBJS-$(CONFIG_WMV2DSP)                += mips/wmv2dsp_mmi.o
 MMI-OBJS-$(CONFIG_HEVC_DECODER)           += mips/hevcdsp_mmi.o
 MMI-OBJS-$(CONFIG_VP3DSP)                 += mips/vp3dsp_idct_mmi.o
 MMI-OBJS-$(CONFIG_VP9_DECODER)            += mips/vp9_mc_mmi.o
-MSA-OBJS-$(CONFIG_VC1_DECODER)            += mips/vc1dsp_msa.o