[v2,01/14] LoongArch: Introduce loongarch32 target

Message ID 20230809115325.3716347-2-c@jia.je
State Unresolved
Headers
Series LoongArch: Add loongarch32 and ilp32 abi |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Jiajie Chen Aug. 9, 2023, 11:46 a.m. UTC
  Introduce loongarch32 target and ilp32 abi variants. The ilp32d abi
variant is selected as the default abi of loongarch32 target.

Currently, ilp32 abi can only be used for loongarch32, but in the
future, it might be possible to use ilp32 abi for loongarch64.

contrib/ChangeLog:

	* config-list.mk: Add loongarch32-linux-gnu*.

gcc/ChangeLog:

	* config.gcc: Add target triple loongarch32-*-*-* and
	corresponding abi ilp32f, ilp32d and ilp32s.
	* config/loongarch/genopts/loongarch-strings: Add strings for
	loongarch32 and ilp32 abi variants.
	* config/loongarch/genopts/loongarch.opt.in: Add
	-march=loongarch32 and -mabi=ilp32d/ilp32f/ilp32s.
	* config/loongarch/gnu-user.h: Add ilp32 abi variants to spec.
	* config/loongarch/linux.h: Add ABI_LIBDIR for ilp32 abi
	variants.
	* config/loongarch/loongarch-c.cc (loongarch_cpu_cpp_builtins):
	Add builtin definitions for loongarch32 target.
	* config/loongarch/loongarch-def.c: Add loongarch32 and ilp32
	definitions.
	* config/loongarch/loongarch-def.h: Add loongarch32 and ilp32
	definitions.
	* config/loongarch/loongarch-driver.h: Add ilp32 abi variants to
	spec.
	* config/loongarch/loongarch-opts.cc: Handle ilp32 abi variants.
	* config/loongarch/loongarch-opts.h: Add loongarch32 case to
	macros.
	* config/loongarch/loongarch-str.h: Add loongarch32 and ilp32
	strings.
	* config/loongarch/loongarch.cc: Disable -fpcc-struct-return for
	ilp32.
	* config/loongarch/loongarch.opt: Add -march=loongarch32 and
	-mabi=ilp32d/ilp32f/ilp32s.
	* config/loongarch/t-linux: Add ilp32 abi variants to multilib.
---
 contrib/config-list.mk                        |  1 +
 gcc/config.gcc                                | 61 ++++++++++++++++---
 .../loongarch/genopts/loongarch-strings       |  5 ++
 gcc/config/loongarch/genopts/loongarch.opt.in | 12 ++++
 gcc/config/loongarch/gnu-user.h               |  3 +
 gcc/config/loongarch/linux.h                  |  8 ++-
 gcc/config/loongarch/loongarch-c.cc           | 12 ++++
 gcc/config/loongarch/loongarch-def.c          | 33 ++++++++++
 gcc/config/loongarch/loongarch-def.h          | 25 +++++---
 gcc/config/loongarch/loongarch-driver.h       |  4 ++
 gcc/config/loongarch/loongarch-opts.cc        | 22 ++++++-
 gcc/config/loongarch/loongarch-opts.h         | 20 ++++--
 gcc/config/loongarch/loongarch-str.h          |  5 ++
 gcc/config/loongarch/loongarch.cc             |  2 +-
 gcc/config/loongarch/loongarch.opt            | 12 ++++
 gcc/config/loongarch/t-linux                  | 16 ++++-
 16 files changed, 210 insertions(+), 31 deletions(-)
  

Comments

Xi Ruoyao Aug. 9, 2023, 2:03 p.m. UTC | #1
On Wed, 2023-08-09 at 19:46 +0800, Jiajie Chen wrote:
> +      builtin_define ("_ABILP32=3");
> +      builtin_define ("_LOONGARCH_SIM=_ABILP32");

Let's remove them.  These MIPS-style definitions are deprecated:
https://github.com/loongson/LoongArch-Documentation/pull/28.

Unfortunately for LP64 ABI _ABILP64 is already a part of public API. 
I've tried to raise a deprecation warning for them, but it seems doing
so needs a major change in libcpp...  However ILP32 ABI is "fresh new"
so we should take the advantage to remove the historic burden.
  

Patch

diff --git a/contrib/config-list.mk b/contrib/config-list.mk
index e570b13c71b..3c00ce5410a 100644
--- a/contrib/config-list.mk
+++ b/contrib/config-list.mk
@@ -57,6 +57,7 @@  LIST = aarch64-elf aarch64-freebsd13 aarch64-linux-gnu aarch64-rtems \
   i686-cygwinOPT-enable-threads=yes i686-mingw32crt ia64-elf \
   ia64-linux ia64-hpux ia64-hp-vms iq2000-elf lm32-elf \
   lm32-rtems lm32-uclinux \
+  loongarch32-linux-gnuf64 loongarch32-linux-gnuf32 loongarch32-linux-gnusf \
   loongarch64-linux-gnuf64 loongarch64-linux-gnuf32 loongarch64-linux-gnusf \
   m32c-elf m32r-elf m32rle-elf \
   m68k-elf m68k-netbsdelf \
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 415e0e1ebc5..45e69b24b44 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -4901,10 +4901,24 @@  case "${target}" in
 			arch_pattern     arch_default   \
 			fpu_pattern      fpu_default    \
 			tune_pattern     tune_default   \
-			triplet_os       triplet_abi
+			triplet_os       triplet_abi    \
+			triplet_cpu
 
 		# Infer ABI from the triplet.
 		case ${target} in
+		loongarch32-*-*-*f64)
+			abi_pattern="ilp32d"
+			;;
+		loongarch32-*-*-*f32)
+			abi_pattern="ilp32f"
+			;;
+		loongarch32-*-*-*sf)
+			abi_pattern="ilp32s"
+			;;
+		loongarch32-*-*-*)
+			abi_pattern="ilp32[dfs]"
+			abi_default="ilp32d"
+			;;
 		loongarch64-*-*-*f64)
 			abi_pattern="lp64d"
 			;;
@@ -4939,7 +4953,7 @@  case "${target}" in
 
 		# Perform initial sanity checks on --with-* options.
 		case ${with_arch} in
-		"" | loongarch64 | la464) ;; # OK, append here.
+		"" | loongarch32 | loongarch64 | la464) ;; # OK, append here.
 		native)
 			if test x${host} != x${target}; then
 				echo "--with-arch=native is illegal for cross-compiler." 1>&2
@@ -4958,7 +4972,7 @@  case "${target}" in
 		esac
 
 		case ${with_abi} in
-		"" | lp64d | lp64f | lp64s) ;; # OK, append here.
+		"" | ilp32d | ilp32f | ilp32s | lp64d | lp64f | lp64s) ;; # OK, append here.
 		*)
 			echo "Unsupported ABI given in --with-abi=$with_abi" 1>&2
 			exit 1
@@ -5007,12 +5021,21 @@  case "${target}" in
 			;;
 		esac
 
+		case ${target} in
+		loongarch32-*-*-*)
+			triplet_cpu="loongarch32"
+			;;
+		loongarch64-*-*-*)
+			triplet_cpu="loongarch64"
+			;;
+		esac
+
 		case ${with_abi} in
-		  "lp64d") triplet_abi="";;
-		  "lp64f") triplet_abi="f32";;
-		  "lp64s") triplet_abi="sf";;
+		  "ilp32d" | "lp64d") triplet_abi="";;
+		  "ilp32f" | "lp64f") triplet_abi="f32";;
+		  "ilp32s" | "lp64s") triplet_abi="sf";;
 		esac
-		la_canonical_triplet="loongarch64-${triplet_os}${triplet_abi}"
+		la_canonical_triplet="${triplet_cpu}-${triplet_os}${triplet_abi}"
 
 		# Set default value for with_abiext (internal)
 		case ${with_abiext} in
@@ -5038,6 +5061,12 @@  case "${target}" in
 
 		# Infer ISA-related default options from the ABI: pass 1
 		case ${with_abi}/${with_abiext} in
+		ilp32*/base)
+			# architectures that support ilp32* ABI
+			arch_pattern="native|loongarch32"
+			# default architecture for ilp32* ABI
+			arch_default="loongarch32"
+			;;
 		lp64*/base)
 			# architectures that support lp64* ABI
 			arch_pattern="native|loongarch64|la464"
@@ -5052,14 +5081,14 @@  case "${target}" in
 
 		# Infer ISA-related default options from the ABI: pass 2
 		case ${with_abi}/${with_abiext} in
-		lp64d/base)
+		ilp32d/base | lp64d/base)
 			fpu_pattern="64"
 			;;
-		lp64f/base)
+		ilp32f/base | lp64f/base)
 			fpu_pattern="32|64"
 			fpu_default="32"
 			;;
-		lp64s/base)
+		ilp32s/base | lp64s/base)
 			fpu_pattern="none|32|64"
 			fpu_default="none"
 			;;
@@ -5118,6 +5147,10 @@  case "${target}" in
 			tune_pattern="*"
 			tune_default="native"
 			;;
+		loongarch32)
+			tune_pattern="loongarch32"
+			tune_default="loongarch32"
+			;;
 		loongarch64)
 			tune_pattern="loongarch64|la464"
 			tune_default="la464"
@@ -5187,6 +5220,9 @@  case "${target}" in
 				1)
 					# Component 1: Base ABI type
 					case ${component} in
+					ilp32d) elem_tmp="ABI_BASE_ILP32D,";;
+					ilp32f) elem_tmp="ABI_BASE_ILP32F,";;
+					ilp32s) elem_tmp="ABI_BASE_ILP32S,";;
 					lp64d) elem_tmp="ABI_BASE_LP64D,";;
 					lp64f) elem_tmp="ABI_BASE_LP64F,";;
 					lp64s) elem_tmp="ABI_BASE_LP64S,";;
@@ -5741,17 +5777,22 @@  case ${target} in
 		# See macro definitions from loongarch-opts.h and loongarch-cpu.h.
 		case ${with_arch} in
 		native)		tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_NATIVE" ;;
+		loongarch32)	tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_LOONGARCH32" ;;
 		la464)		tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_LA464" ;;
 		loongarch64)	tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_LOONGARCH64" ;;
 		esac
 
 		case ${with_tune} in
 		native)		tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_NATIVE" ;;
+		loongarch32)	tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_LOONGARCH32" ;;
 		la464)		tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_LA464" ;;
 		loongarch64)	tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_LOONGARCH64" ;;
 		esac
 
 		case ${with_abi} in
+		ilp32d)     tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_ILP32D" ;;
+		ilp32f)     tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_ILP32F" ;;
+		ilp32s)     tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_ILP32S" ;;
 		lp64d)     tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_LP64D" ;;
 		lp64f)     tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_LP64F" ;;
 		lp64s)     tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_LP64S" ;;
diff --git a/gcc/config/loongarch/genopts/loongarch-strings b/gcc/config/loongarch/genopts/loongarch-strings
index a40998ead97..1e20b70dde2 100644
--- a/gcc/config/loongarch/genopts/loongarch-strings
+++ b/gcc/config/loongarch/genopts/loongarch-strings
@@ -23,10 +23,12 @@  OPTSTR_ARCH	      arch
 OPTSTR_TUNE	      tune
 
 STR_CPU_NATIVE	      native
+STR_CPU_LOONGARCH32   loongarch32
 STR_CPU_LOONGARCH64   loongarch64
 STR_CPU_LA464	      la464
 
 # Base architecture
+STR_ISA_BASE_LA32V100 la32
 STR_ISA_BASE_LA64V100 la64
 
 # -mfpu
@@ -42,6 +44,9 @@  OPTSTR_DOUBLE_FLOAT   double-float
 
 # -mabi=
 OPTSTR_ABI_BASE	      abi
+STR_ABI_BASE_ILP32D   ilp32d
+STR_ABI_BASE_ILP32F   ilp32f
+STR_ABI_BASE_ILP32S   ilp32s
 STR_ABI_BASE_LP64D    lp64d
 STR_ABI_BASE_LP64F    lp64f
 STR_ABI_BASE_LP64S    lp64s
diff --git a/gcc/config/loongarch/genopts/loongarch.opt.in b/gcc/config/loongarch/genopts/loongarch.opt.in
index 4b9b4ac273e..47f77345890 100644
--- a/gcc/config/loongarch/genopts/loongarch.opt.in
+++ b/gcc/config/loongarch/genopts/loongarch.opt.in
@@ -85,6 +85,9 @@  LoongArch CPU types:
 EnumValue
 Enum(cpu_type) String(@@STR_CPU_NATIVE@@) Value(CPU_NATIVE)
 
+EnumValue
+Enum(cpu_type) String(@@STR_CPU_LOONGARCH32@@) Value(CPU_LOONGARCH32)
+
 EnumValue
 Enum(cpu_type) String(@@STR_CPU_LOONGARCH64@@) Value(CPU_LOONGARCH64)
 
@@ -108,6 +111,15 @@  Enum
 Name(abi_base) Type(int)
 Base ABI types for LoongArch:
 
+EnumValue
+Enum(abi_base) String(@@STR_ABI_BASE_ILP32D@@) Value(ABI_BASE_ILP32D)
+
+EnumValue
+Enum(abi_base) String(@@STR_ABI_BASE_ILP32F@@) Value(ABI_BASE_ILP32F)
+
+EnumValue
+Enum(abi_base) String(@@STR_ABI_BASE_ILP32S@@) Value(ABI_BASE_ILP32S)
+
 EnumValue
 Enum(abi_base) String(@@STR_ABI_BASE_LP64D@@) Value(ABI_BASE_LP64D)
 
diff --git a/gcc/config/loongarch/gnu-user.h b/gcc/config/loongarch/gnu-user.h
index fa1a5211419..bf6d3a4fe98 100644
--- a/gcc/config/loongarch/gnu-user.h
+++ b/gcc/config/loongarch/gnu-user.h
@@ -34,6 +34,9 @@  along with GCC; see the file COPYING3.  If not see
   "/lib" ABI_GRLEN_SPEC "/ld-linux-loongarch-" ABI_SPEC ".so.1"
 
 #define MUSL_ABI_SPEC \
+  "%{mabi=ilp32d:-ilp32d}" \
+  "%{mabi=ilp32f:-ilp32f}" \
+  "%{mabi=ilp32s:-ilp32s}" \
   "%{mabi=lp64d:-lp64d}" \
   "%{mabi=lp64f:-lp64f}" \
   "%{mabi=lp64s:-lp64s}"
diff --git a/gcc/config/loongarch/linux.h b/gcc/config/loongarch/linux.h
index 9059d244190..45aa3531cd3 100644
--- a/gcc/config/loongarch/linux.h
+++ b/gcc/config/loongarch/linux.h
@@ -23,7 +23,13 @@  along with GCC; see the file COPYING3.  If not see
 
 #if defined(LA_DISABLE_MULTILIB) && defined(LA_DISABLE_MULTIARCH)
 
-  #if DEFAULT_ABI_BASE == ABI_BASE_LP64D
+  #if DEFAULT_ABI_BASE == ABI_BASE_ILP32D
+    #define ABI_LIBDIR "lib32"
+  #elif DEFAULT_ABI_BASE == ABI_BASE_ILP32F
+    #define ABI_LIBDIR "lib32/f32"
+  #elif DEFAULT_ABI_BASE == ABI_BASE_ILP32S
+    #define ABI_LIBDIR "lib32/sf"
+  #elif DEFAULT_ABI_BASE == ABI_BASE_LP64D
     #define ABI_LIBDIR "lib64"
   #elif DEFAULT_ABI_BASE == ABI_BASE_LP64F
     #define ABI_LIBDIR "lib64/f32"
diff --git a/gcc/config/loongarch/loongarch-c.cc b/gcc/config/loongarch/loongarch-c.cc
index 67911b78f28..e3783a325d7 100644
--- a/gcc/config/loongarch/loongarch-c.cc
+++ b/gcc/config/loongarch/loongarch-c.cc
@@ -65,12 +65,24 @@  loongarch_cpu_cpp_builtins (cpp_reader *pfile)
   LARCH_CPP_SET_PROCESSOR ("_LOONGARCH_TUNE", LARCH_ACTUAL_TUNE);
 
   /* Base architecture / ABI.  */
+  if (TARGET_32BIT)
+    {
+      builtin_define ("__loongarch_grlen=32");
+      builtin_define ("__loongarch32");
+    }
   if (TARGET_64BIT)
     {
       builtin_define ("__loongarch_grlen=64");
       builtin_define ("__loongarch64");
     }
 
+  if (TARGET_ABI_ILP32)
+    {
+      builtin_define ("_ABILP32=3");
+      builtin_define ("_LOONGARCH_SIM=_ABILP32");
+      builtin_define ("__loongarch_ilp32");
+    }
+
   if (TARGET_ABI_LP64)
     {
       builtin_define ("_ABILP64=3");
diff --git a/gcc/config/loongarch/loongarch-def.c b/gcc/config/loongarch/loongarch-def.c
index 6729c857f7c..5ae8bd24c9f 100644
--- a/gcc/config/loongarch/loongarch-def.c
+++ b/gcc/config/loongarch/loongarch-def.c
@@ -40,12 +40,17 @@  along with GCC; see the file COPYING3.  If not see
 const char*
 loongarch_cpu_strings[N_TUNE_TYPES] = {
   [CPU_NATIVE]		  = STR_CPU_NATIVE,
+  [CPU_LOONGARCH32]	  = STR_CPU_LOONGARCH32,
   [CPU_LOONGARCH64]	  = STR_CPU_LOONGARCH64,
   [CPU_LA464]		  = STR_CPU_LA464,
 };
 
 struct loongarch_isa
 loongarch_cpu_default_isa[N_ARCH_TYPES] = {
+  [CPU_LOONGARCH32] = {
+      .base = ISA_BASE_LA32V100,
+      .fpu = ISA_EXT_FPU32,
+  },
   [CPU_LOONGARCH64] = {
       .base = ISA_BASE_LA64V100,
       .fpu = ISA_EXT_FPU64,
@@ -58,6 +63,12 @@  loongarch_cpu_default_isa[N_ARCH_TYPES] = {
 
 struct loongarch_cache
 loongarch_cpu_cache[N_TUNE_TYPES] = {
+  [CPU_LOONGARCH32] = {
+      .l1d_line_size = 64,
+      .l1d_size = 64,
+      .l2d_size = 256,
+      .simultaneous_prefetches = 4,
+  },
   [CPU_LOONGARCH64] = {
       .l1d_line_size = 64,
       .l1d_size = 64,
@@ -74,6 +85,10 @@  loongarch_cpu_cache[N_TUNE_TYPES] = {
 
 struct loongarch_align
 loongarch_cpu_align[N_TUNE_TYPES] = {
+  [CPU_LOONGARCH32] = {
+    .function = "32",
+    .label = "16",
+  },
   [CPU_LOONGARCH64] = {
     .function = "32",
     .label = "16",
@@ -94,6 +109,9 @@  loongarch_cpu_rtx_cost_data[N_TUNE_TYPES] = {
   [CPU_NATIVE] = {
       DEFAULT_COSTS
   },
+  [CPU_LOONGARCH32] = {
+      DEFAULT_COSTS
+  },
   [CPU_LOONGARCH64] = {
       DEFAULT_COSTS
   },
@@ -121,6 +139,7 @@  loongarch_rtx_cost_optimize_size = {
 int
 loongarch_cpu_issue_rate[N_TUNE_TYPES] = {
   [CPU_NATIVE]	      = 4,
+  [CPU_LOONGARCH32]   = 4,
   [CPU_LOONGARCH64]   = 4,
   [CPU_LA464]	      = 4,
 };
@@ -128,6 +147,7 @@  loongarch_cpu_issue_rate[N_TUNE_TYPES] = {
 int
 loongarch_cpu_multipass_dfa_lookahead[N_TUNE_TYPES] = {
   [CPU_NATIVE]	      = 4,
+  [CPU_LOONGARCH32]   = 4,
   [CPU_LOONGARCH64]   = 4,
   [CPU_LA464]	      = 4,
 };
@@ -139,6 +159,7 @@  loongarch_cpu_multipass_dfa_lookahead[N_TUNE_TYPES] = {
 
 const char*
 loongarch_isa_base_strings[N_ISA_BASE_TYPES] = {
+  [ISA_BASE_LA32V100] = STR_ISA_BASE_LA32V100,
   [ISA_BASE_LA64V100] = STR_ISA_BASE_LA64V100,
 };
 
@@ -151,6 +172,9 @@  loongarch_isa_ext_strings[N_ISA_EXT_TYPES] = {
 
 const char*
 loongarch_abi_base_strings[N_ABI_BASE_TYPES] = {
+  [ABI_BASE_ILP32D] = STR_ABI_BASE_ILP32D,
+  [ABI_BASE_ILP32F] = STR_ABI_BASE_ILP32F,
+  [ABI_BASE_ILP32S] = STR_ABI_BASE_ILP32S,
   [ABI_BASE_LP64D] = STR_ABI_BASE_LP64D,
   [ABI_BASE_LP64F] = STR_ABI_BASE_LP64F,
   [ABI_BASE_LP64S] = STR_ABI_BASE_LP64S,
@@ -182,6 +206,15 @@  loongarch_switch_strings[] = {
 /* ABI-related definitions.  */
 const struct loongarch_isa
 abi_minimal_isa[N_ABI_BASE_TYPES][N_ABI_EXT_TYPES] = {
+  [ABI_BASE_ILP32D] = {
+      [ABI_EXT_BASE] = {.base = ISA_BASE_LA32V100, .fpu = ISA_EXT_FPU64},
+  },
+  [ABI_BASE_ILP32F] = {
+      [ABI_EXT_BASE] = {.base = ISA_BASE_LA32V100, .fpu = ISA_EXT_FPU32},
+  },
+  [ABI_BASE_ILP32S] = {
+      [ABI_EXT_BASE] = {.base = ISA_BASE_LA32V100, .fpu = ISA_EXT_NOFPU},
+  },
   [ABI_BASE_LP64D] = {
       [ABI_EXT_BASE] = {.base = ISA_BASE_LA64V100, .fpu = ISA_EXT_FPU64},
   },
diff --git a/gcc/config/loongarch/loongarch-def.h b/gcc/config/loongarch/loongarch-def.h
index fb8bb88eb52..6c4b9fa3385 100644
--- a/gcc/config/loongarch/loongarch-def.h
+++ b/gcc/config/loongarch/loongarch-def.h
@@ -54,8 +54,9 @@  extern "C" {
 
 /* enum isa_base */
 extern const char* loongarch_isa_base_strings[];
-#define ISA_BASE_LA64V100     0
-#define N_ISA_BASE_TYPES      1
+#define ISA_BASE_LA32V100     0
+#define ISA_BASE_LA64V100     1
+#define N_ISA_BASE_TYPES      2
 
 /* enum isa_ext_* */
 extern const char* loongarch_isa_ext_strings[];
@@ -67,10 +68,13 @@  extern const char* loongarch_isa_ext_strings[];
 
 /* enum abi_base */
 extern const char* loongarch_abi_base_strings[];
-#define ABI_BASE_LP64D	      0
-#define ABI_BASE_LP64F	      1
-#define ABI_BASE_LP64S	      2
-#define N_ABI_BASE_TYPES      3
+#define ABI_BASE_ILP32D	      0
+#define ABI_BASE_ILP32F	      1
+#define ABI_BASE_ILP32S	      2
+#define ABI_BASE_LP64D	      3
+#define ABI_BASE_LP64F	      4
+#define ABI_BASE_LP64S	      5
+#define N_ABI_BASE_TYPES      6
 
 /* enum abi_ext */
 extern const char* loongarch_abi_ext_strings[];
@@ -132,10 +136,11 @@  struct loongarch_target
 /* CPU properties.  */
 /* index */
 #define CPU_NATIVE	  0
-#define CPU_LOONGARCH64	  1
-#define CPU_LA464	  2
-#define N_ARCH_TYPES	  3
-#define N_TUNE_TYPES	  3
+#define CPU_LOONGARCH32	  1
+#define CPU_LOONGARCH64	  2
+#define CPU_LA464	  3
+#define N_ARCH_TYPES	  4
+#define N_TUNE_TYPES	  4
 
 /* parallel tables.  */
 extern const char* loongarch_cpu_strings[];
diff --git a/gcc/config/loongarch/loongarch-driver.h b/gcc/config/loongarch/loongarch-driver.h
index ba8817a4621..0a22acab803 100644
--- a/gcc/config/loongarch/loongarch-driver.h
+++ b/gcc/config/loongarch/loongarch-driver.h
@@ -58,9 +58,13 @@  driver_get_normalized_m_opts (int argc, const char **argv);
 
 /* ABI spec strings.  */
 #define ABI_GRLEN_SPEC \
+  "%{mabi=ilp32*:32}"   \
   "%{mabi=lp64*:64}"   \
 
 #define ABI_SPEC \
+  "%{mabi=ilp32d:ilp32d}" \
+  "%{mabi=ilp32f:ilp32f}" \
+  "%{mabi=ilp32s:ilp32s}" \
   "%{mabi=lp64d:lp64d}" \
   "%{mabi=lp64f:lp64f}" \
   "%{mabi=lp64s:lp64s}" \
diff --git a/gcc/config/loongarch/loongarch-opts.cc b/gcc/config/loongarch/loongarch-opts.cc
index a52e25236ea..9fc0bbbcb6e 100644
--- a/gcc/config/loongarch/loongarch-opts.cc
+++ b/gcc/config/loongarch/loongarch-opts.cc
@@ -36,6 +36,9 @@  struct loongarch_target la_target;
 #define ABI_COUNT (sizeof(abi_priority_list)/sizeof(struct loongarch_abi))
 static const struct loongarch_abi
 abi_priority_list[] = {
+    {ABI_BASE_ILP32D, ABI_EXT_BASE},
+    {ABI_BASE_ILP32F, ABI_EXT_BASE},
+    {ABI_BASE_ILP32S, ABI_EXT_BASE},
     {ABI_BASE_LP64D, ABI_EXT_BASE},
     {ABI_BASE_LP64F, ABI_EXT_BASE},
     {ABI_BASE_LP64S, ABI_EXT_BASE},
@@ -410,17 +413,23 @@  isa_default_abi (const struct loongarch_isa *isa)
   switch (isa->fpu)
     {
       case ISA_EXT_FPU64:
-	if (isa->base == ISA_BASE_LA64V100)
+	if (isa->base == ISA_BASE_LA32V100)
+	  abi.base = ABI_BASE_ILP32D;
+	else if (isa->base == ISA_BASE_LA64V100)
 	  abi.base = ABI_BASE_LP64D;
 	break;
 
       case ISA_EXT_FPU32:
-	if (isa->base == ISA_BASE_LA64V100)
+	if (isa->base == ISA_BASE_LA32V100)
+	  abi.base = ABI_BASE_ILP32F;
+	else if (isa->base == ISA_BASE_LA64V100)
 	  abi.base = ABI_BASE_LP64F;
 	break;
 
       case ISA_EXT_NOFPU:
-	if (isa->base == ISA_BASE_LA64V100)
+	if (isa->base == ISA_BASE_LA32V100)
+	  abi.base = ABI_BASE_ILP32S;
+	else if (isa->base == ISA_BASE_LA64V100)
 	  abi.base = ABI_BASE_LP64S;
 	break;
 
@@ -439,6 +448,8 @@  isa_base_compat_p (const struct loongarch_isa *set1,
 {
   switch (set2->base)
     {
+      case ISA_BASE_LA32V100:
+	return (set1->base == ISA_BASE_LA32V100);
       case ISA_BASE_LA64V100:
 	return (set1->base == ISA_BASE_LA64V100);
 
@@ -487,6 +498,11 @@  abi_default_cpu_arch (struct loongarch_abi abi)
 {
   switch (abi.base)
     {
+      case ABI_BASE_ILP32D:
+      case ABI_BASE_ILP32F:
+      case ABI_BASE_ILP32S:
+	if (abi.ext == ABI_EXT_BASE)
+	  return CPU_LOONGARCH32;
       case ABI_BASE_LP64D:
       case ABI_BASE_LP64F:
       case ABI_BASE_LP64S:
diff --git a/gcc/config/loongarch/loongarch-opts.h b/gcc/config/loongarch/loongarch-opts.h
index b1ff54426e4..c8794dff0ad 100644
--- a/gcc/config/loongarch/loongarch-opts.h
+++ b/gcc/config/loongarch/loongarch-opts.h
@@ -51,15 +51,25 @@  loongarch_config_target (struct loongarch_target *target,
 #define TARGET_CMODEL_EXTREME	    (la_target.cmodel == CMODEL_EXTREME)
 
 #define TARGET_HARD_FLOAT	    (la_target.isa.fpu != ISA_EXT_NOFPU)
-#define TARGET_HARD_FLOAT_ABI	    (la_target.abi.base == ABI_BASE_LP64D \
+#define TARGET_HARD_FLOAT_ABI	    (la_target.abi.base == ABI_BASE_ILP32D \
+				     || la_target.abi.base == ABI_BASE_ILP32F \
+				     || la_target.abi.base == ABI_BASE_LP64D \
 				     || la_target.abi.base == ABI_BASE_LP64F)
 
 #define TARGET_SOFT_FLOAT	  (la_target.isa.fpu == ISA_EXT_NOFPU)
-#define TARGET_SOFT_FLOAT_ABI	  (la_target.abi.base == ABI_BASE_LP64S)
+#define TARGET_SOFT_FLOAT_ABI	  (la_target.abi.base == ABI_BASE_ILP32S \
+				     || la_target.abi.base == ABI_BASE_LP64S)
 #define TARGET_SINGLE_FLOAT	  (la_target.isa.fpu == ISA_EXT_FPU32)
-#define TARGET_SINGLE_FLOAT_ABI	  (la_target.abi.base == ABI_BASE_LP64F)
+#define TARGET_SINGLE_FLOAT_ABI	  (la_target.abi.base == ABI_BASE_ILP32F \
+				     || la_target.abi.base == ABI_BASE_LP64F)
 #define TARGET_DOUBLE_FLOAT	  (la_target.isa.fpu == ISA_EXT_FPU64)
-#define TARGET_DOUBLE_FLOAT_ABI	  (la_target.abi.base == ABI_BASE_LP64D)
+#define TARGET_DOUBLE_FLOAT_ABI	  (la_target.abi.base == ABI_BASE_ILP32D \
+				     || la_target.abi.base == ABI_BASE_LP64D)
+
+#define TARGET_32BIT		  (la_target.isa.base == ISA_BASE_LA32V100)
+#define TARGET_ABI_ILP32	  (la_target.abi.base == ABI_BASE_ILP32D \
+				   || la_target.abi.base == ABI_BASE_ILP32F \
+				   || la_target.abi.base == ABI_BASE_ILP32S)
 
 #define TARGET_64BIT		  (la_target.isa.base == ISA_BASE_LA64V100)
 #define TARGET_ABI_LP64		  (la_target.abi.base == ABI_BASE_LP64D	\
@@ -78,9 +88,11 @@  loongarch_config_target (struct loongarch_target *target,
 				    ? (la_target.cpu_native) : (CPU_NATIVE)) \
 				    : (la_target.cpu_tune))
 
+#define TARGET_ARCH_LOONGARCH32	  (LARCH_ACTUAL_ARCH == CPU_LOONGARCH32)
 #define TARGET_ARCH_LOONGARCH64	  (LARCH_ACTUAL_ARCH == CPU_LOONGARCH64)
 #define TARGET_ARCH_LA464	  (LARCH_ACTUAL_ARCH == CPU_LA464)
 
+#define TARGET_TUNE_LOONGARCH32	  (LARCH_ACTUAL_TUNE == CPU_LOONGARCH32)
 #define TARGET_TUNE_LOONGARCH64	  (LARCH_ACTUAL_TUNE == CPU_LOONGARCH64)
 #define TARGET_TUNE_LA464	  (LARCH_ACTUAL_TUNE == CPU_LA464)
 
diff --git a/gcc/config/loongarch/loongarch-str.h b/gcc/config/loongarch/loongarch-str.h
index af2e82a321f..60588da45e2 100644
--- a/gcc/config/loongarch/loongarch-str.h
+++ b/gcc/config/loongarch/loongarch-str.h
@@ -27,9 +27,11 @@  along with GCC; see the file COPYING3.  If not see
 #define OPTSTR_TUNE "tune"
 
 #define STR_CPU_NATIVE "native"
+#define STR_CPU_LOONGARCH32 "loongarch32"
 #define STR_CPU_LOONGARCH64 "loongarch64"
 #define STR_CPU_LA464 "la464"
 
+#define STR_ISA_BASE_LA32V100 "la32"
 #define STR_ISA_BASE_LA64V100 "la64"
 
 #define OPTSTR_ISA_EXT_FPU "fpu"
@@ -43,6 +45,9 @@  along with GCC; see the file COPYING3.  If not see
 #define OPTSTR_DOUBLE_FLOAT "double-float"
 
 #define OPTSTR_ABI_BASE "abi"
+#define STR_ABI_BASE_ILP32D "ilp32d"
+#define STR_ABI_BASE_ILP32F "ilp32f"
+#define STR_ABI_BASE_ILP32S "ilp32s"
 #define STR_ABI_BASE_LP64D "lp64d"
 #define STR_ABI_BASE_LP64F "lp64f"
 #define STR_ABI_BASE_LP64S "lp64s"
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
index 86d58784113..c980de98758 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -6209,7 +6209,7 @@  loongarch_option_override_internal (struct gcc_options *opts)
 			   la_opt_cpu_arch, la_opt_cpu_tune, la_opt_fpu,
 			   la_opt_abi_base, la_opt_abi_ext, la_opt_cmodel, 0);
 
-  if (TARGET_ABI_LP64)
+  if (TARGET_ABI_LP64 || TARGET_ABI_ILP32)
     flag_pcc_struct_return = 0;
 
   /* Decide which rtx_costs structure to use.  */
diff --git a/gcc/config/loongarch/loongarch.opt b/gcc/config/loongarch/loongarch.opt
index 68018ade73f..2cd36c5e8fa 100644
--- a/gcc/config/loongarch/loongarch.opt
+++ b/gcc/config/loongarch/loongarch.opt
@@ -92,6 +92,9 @@  LoongArch CPU types:
 EnumValue
 Enum(cpu_type) String(native) Value(CPU_NATIVE)
 
+EnumValue
+Enum(cpu_type) String(loongarch32) Value(CPU_LOONGARCH32)
+
 EnumValue
 Enum(cpu_type) String(loongarch64) Value(CPU_LOONGARCH64)
 
@@ -115,6 +118,15 @@  Enum
 Name(abi_base) Type(int)
 Base ABI types for LoongArch:
 
+EnumValue
+Enum(abi_base) String(ilp32d) Value(ABI_BASE_ILP32D)
+
+EnumValue
+Enum(abi_base) String(ilp32f) Value(ABI_BASE_ILP32F)
+
+EnumValue
+Enum(abi_base) String(ilp32s) Value(ABI_BASE_ILP32S)
+
 EnumValue
 Enum(abi_base) String(lp64d) Value(ABI_BASE_LP64D)
 
diff --git a/gcc/config/loongarch/t-linux b/gcc/config/loongarch/t-linux
index e40da179203..1718c3e11a2 100644
--- a/gcc/config/loongarch/t-linux
+++ b/gcc/config/loongarch/t-linux
@@ -17,8 +17,8 @@ 
 # <http://www.gnu.org/licenses/>.
 
 # Multilib
-MULTILIB_OPTIONS = mabi=lp64d/mabi=lp64f/mabi=lp64s
-MULTILIB_DIRNAMES = base/lp64d base/lp64f base/lp64s
+MULTILIB_OPTIONS = mabi=ilp32d/mabi=ilp32f/mabi=ilp32s/mabi=lp64d/mabi=lp64f/mabi=lp64s
+MULTILIB_DIRNAMES = base/ilp32d base/ilp32f base/ilp32s base/lp64d base/lp64f base/lp64s
 
 # The GCC driver always gets all abi-related options on the command line.
 # (see loongarch-driver.c:driver_get_normalized_m_opts)
@@ -38,6 +38,18 @@  endif
 # Don't define MULTILIB_OSDIRNAMES if multilib is disabled.
 ifeq ($(filter LA_DISABLE_MULTILIB,$(tm_defines)),)
 
+    MULTILIB_OSDIRNAMES = \
+      mabi.ilp32d=../lib32$\
+      $(call if_multiarch,:loongarch32-linux-gnu)
+
+    MULTILIB_OSDIRNAMES += \
+      mabi.ilp32f=../lib32/f32$\
+      $(call if_multiarch,:loongarch32-linux-gnuf32)
+
+    MULTILIB_OSDIRNAMES += \
+      mabi.ilp32s=../lib32/sf$\
+      $(call if_multiarch,:loongarch32-linux-gnusf)
+
     MULTILIB_OSDIRNAMES = \
       mabi.lp64d=../lib64$\
       $(call if_multiarch,:loongarch64-linux-gnu)