diff --git a/configure b/configure
index 7495f35faa..8952c7c6fb 100755
--- a/configure
+++ b/configure
@@ -2551,7 +2551,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"
 
@@ -5002,8 +5002,6 @@ elif enabled bfin; then
 
 elif enabled mips; then
 
-    cpuflags="-march=$cpu"
-
     if [ "$cpu" != "generic" ]; then
         disable mips32r2
         disable mips32r5
@@ -5012,19 +5010,61 @@ elif enabled mips; then
         disable mips64r6
         disable loongson2
         disable loongson3
+        disable mipsdsp
+        disable mipsdspr2
+        disable msa
+        disable mmi
+
+        cpuflags="-march=$cpu"
 
         case $cpu in
-            24kc|24kf*|24kec|34kc|1004kc|24kef*|34kf*|1004kf*|74kc|74kf)
+            # General ISA levels
+            mips1|mips3)
+            ;;
+            mips32r2)
+                enable msa
                 enable mips32r2
-                disable msa
             ;;
-            p5600|i6400|p6600)
-                disable mipsdsp
-                disable mipsdspr2
+            mips32r5)
+                enable msa
+                enable mips32r2
+                enable mips32r5
             ;;
-            loongson*)
-                enable loongson2
+            mips64r2|mips64r5)
+                enable msa
+                enable mmi
+                enable mips64r2
                 enable loongson3
+            ;;
+            # Cores from MIPS(MTI)
+            24kc)
+                disable mipsfpu
+                enable mips32r2
+            ;;
+            24kf*|24kec|34kc|74Kc|1004kc)
+                enable mips32r2
+            ;;
+            24kef*|34kf*|1004kf*)
+                enable mipsdsp
+                enable mips32r2
+            ;;
+            p5600)
+                enable msa
+                enable mips32r2
+                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"
+            ;;
+            # Cores from Loongson
+            loongson2e|loongson2f|loongson3*)
+                enable mmi
                 enable local_aligned
                 enable simd_align_16
                 enable fast_64bit
@@ -5032,75 +5072,43 @@ 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)
-                    if [ "$(echo "$gcc_version 5.3.0" | tr " " "\n" | sort -rV | head -n 1)" == "$gcc_version" ]; then
-                        expensive_optimization_flag=""
-                    else
+                if test "$cc_type" = "gcc"; then
+                    case $gcc_basever in
+                        2|2.*|3.*|4.*|5.0|5.1|5.2)
                         expensive_optimization_flag="-fno-expensive-optimizations"
-                    fi
+                        ;;
+                        *)
+                        expensive_optimization_flag=""
+                        ;;
+                    esac
                 fi
+
                 case $cpu in
                     loongson3*)
+                        enable loongson3
+                        enable msa
                         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.
+        disable mipsdsp
+        disable mipsdspr2
+        # Disable DSP stuff for generic CPU, it can't be detected at runtime.
         warn 'generic cpu selected'
     fi
 
@@ -5847,28 +5855,42 @@ 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 mipsfpu && 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"' && disable loongson3
+
+    # loongson3 is paired with MMI
+    enabled loongson3 && check_inline_asm loongson3 '"gsldxc1 $f0, 0($2, $3)"' '-mloongson-ext' && append MMIFLAGS '-mloongson-ext'
+
+    # 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
@@ -7443,6 +7465,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..13e13553b8 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) $($(2)) $($(1)_DEPFLAGS) $($(1)_C) $($(1)_O) $(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
