From d90639476f7769578682cbf34628968a3428ebec Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Tue, 30 Jun 2015 16:40:19 +0000 Subject: [PATCH] IA MCU psABI support: GCC changes This patch introduces basic IA MCU psABI support into GCC. * configure.ac (ospace_frag): Enable for i?86*-*-elfiamcu target. * configure: Regenerate. gcc/ * config.gcc: Support i[34567]86-*-elfiamcu target. * config/i386/iamcu.h: New. * config/i386/i386.opt: Add -miamcu. * doc/invoke.texi: Document -miamcu. * common/config/i386/i386-common.c (ix86_handle_option): Turn off x87/MMX/SSE/AVX codegen for -miamcu. * config/i386/i386-c.c (ix86_target_macros_internal): Define __iamcu/__iamcu__ for -miamcu. * config/i386/i386.h (PREFERRED_STACK_BOUNDARY_DEFAULT): Set to MIN_STACK_BOUNDARY if TARGET_IAMCU is true. (BIGGEST_ALIGNMENT): Set to 32 if TARGET_IAMCU is true. * config/i386/i386.c (ix86_option_override_internal): Ignore and warn -mregparm for Intel MCU. Turn on -mregparm=3 for Intel MCU by default. Default long double to 64-bit for Intel MCU. Turn on -freg-struct-return for Intel MCU. Issue an error when -miamcu is used in 64-bit or x32 mode or if x87, MMX, SSE or AVX is turned on. (function_arg_advance_32): Pass value whose size is no larger than 8 bytes in registers for Intel MCU. (function_arg_32): Likewise. (ix86_return_in_memory): Return value whose size is no larger than 8 bytes in registers for Intel MCU. (iamcu_alignment): New function. (ix86_data_alignment): Call iamcu_alignment if TARGET_IAMCU is true. (ix86_local_alignment): Don't increase alignment for Intel MCU. (x86_field_alignment): Return iamcu_alignment if TARGET_IAMCU is true. From-SVN: r225197 --- ChangeLog | 6 ++ configure | 2 +- configure.ac | 2 +- gcc/ChangeLog | 31 ++++++++ gcc/common/config/i386/i386-common.c | 16 +++- gcc/config.gcc | 3 + gcc/config/i386/i386-c.c | 5 ++ gcc/config/i386/i386.c | 105 +++++++++++++++++++++++++-- gcc/config/i386/i386.h | 5 +- gcc/config/i386/i386.opt | 4 + gcc/config/i386/iamcu.h | 42 +++++++++++ gcc/doc/invoke.texi | 7 +- 12 files changed, 216 insertions(+), 12 deletions(-) create mode 100644 gcc/config/i386/iamcu.h diff --git a/ChangeLog b/ChangeLog index 1bc0be28483..5ef6a7ad0c0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-06-30 H.J. Lu + + * configure.ac (ospace_frag): Enable for i?86*-*-elfiamcu + target. + * configure: Regenerate. + 2015-06-23 Ludovic Courtès * MAINTAINERS (Write After Approval): Add myself. diff --git a/configure b/configure index bced9de413e..82e45f3bd39 100755 --- a/configure +++ b/configure @@ -6914,7 +6914,7 @@ case "${enable_target_optspace}:${target}" in :d30v-*) ospace_frag="config/mt-d30v" ;; - :m32r-* | :d10v-* | :fr30-*) + :m32r-* | :d10v-* | :fr30-* | :i?86*-*-elfiamcu) ospace_frag="config/mt-ospace" ;; no:* | :*) diff --git a/configure.ac b/configure.ac index 7c06e6ba9fa..dc77a1baeda 100644 --- a/configure.ac +++ b/configure.ac @@ -2560,7 +2560,7 @@ case "${enable_target_optspace}:${target}" in :d30v-*) ospace_frag="config/mt-d30v" ;; - :m32r-* | :d10v-* | :fr30-*) + :m32r-* | :d10v-* | :fr30-* | :i?86*-*-elfiamcu) ospace_frag="config/mt-ospace" ;; no:* | :*) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 92953b2f3f2..bd460912172 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,34 @@ +2015-06-30 H.J. Lu + + * config.gcc: Support i[34567]86-*-elfiamcu target. + * config/i386/iamcu.h: New. + * config/i386/i386.opt: Add -miamcu. + * doc/invoke.texi: Document -miamcu. + * common/config/i386/i386-common.c (ix86_handle_option): Turn + off x87/MMX/SSE/AVX codegen for -miamcu. + * config/i386/i386-c.c (ix86_target_macros_internal): Define + __iamcu/__iamcu__ for -miamcu. + * config/i386/i386.h (PREFERRED_STACK_BOUNDARY_DEFAULT): Set + to MIN_STACK_BOUNDARY if TARGET_IAMCU is true. + (BIGGEST_ALIGNMENT): Set to 32 if TARGET_IAMCU is true. + * config/i386/i386.c (ix86_option_override_internal): Ignore and + warn -mregparm for Intel MCU. Turn on -mregparm=3 for Intel + MCU by default. Default long double to 64-bit for Intel MCU. + Turn on -freg-struct-return for Intel MCU. Issue an error when + -miamcu is used in 64-bit or x32 mode or if x87, MMX, SSE or + AVX is turned on. + (function_arg_advance_32): Pass value whose size is no larger + than 8 bytes in registers for Intel MCU. + (function_arg_32): Likewise. + (ix86_return_in_memory): Return value whose size is no larger + than 8 bytes in registers for Intel MCU. + (iamcu_alignment): New function. + (ix86_data_alignment): Call iamcu_alignment if TARGET_IAMCU is + true. + (ix86_local_alignment): Don't increase alignment for Intel MCU. + (x86_field_alignment): Return iamcu_alignment if TARGET_IAMCU is + true. + 2015-06-30 Marek Polacek * match.pd (X - (X / Y) * Y): Use convert1 and convert2. Convert diff --git a/gcc/common/config/i386/i386-common.c b/gcc/common/config/i386/i386-common.c index 0f8c3e1df04..79b2472dc75 100644 --- a/gcc/common/config/i386/i386-common.c +++ b/gcc/common/config/i386/i386-common.c @@ -223,7 +223,7 @@ along with GCC; see the file COPYING3. If not see bool ix86_handle_option (struct gcc_options *opts, - struct gcc_options *opts_set ATTRIBUTE_UNUSED, + struct gcc_options *opts_set, const struct cl_decoded_option *decoded, location_t loc) { @@ -232,6 +232,20 @@ ix86_handle_option (struct gcc_options *opts, switch (code) { + case OPT_miamcu: + if (value) + { + /* Turn off x87/MMX/SSE/AVX codegen for -miamcu. */ + opts->x_target_flags &= ~MASK_80387; + opts_set->x_target_flags |= MASK_80387; + opts->x_ix86_isa_flags &= ~(OPTION_MASK_ISA_MMX_UNSET + | OPTION_MASK_ISA_SSE_UNSET); + opts->x_ix86_isa_flags_explicit |= (OPTION_MASK_ISA_MMX_UNSET + | OPTION_MASK_ISA_SSE_UNSET); + + } + return true; + case OPT_mmmx: if (value) { diff --git a/gcc/config.gcc b/gcc/config.gcc index 805638d7261..2b3af82be94 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -1389,6 +1389,9 @@ x86_64-*-darwin*) tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc" tm_file="${tm_file} ${cpu_type}/darwin64.h" ;; +i[34567]86-*-elfiamcu) + tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/iamcu.h" + ;; i[34567]86-*-elf*) tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h" ;; diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c index d5063457b90..304ce551d20 100644 --- a/gcc/config/i386/i386-c.c +++ b/gcc/config/i386/i386-c.c @@ -425,6 +425,11 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag, def_or_undef (parse_in, "__CLWB__"); if (isa_flag & OPTION_MASK_ISA_MWAITX) def_or_undef (parse_in, "__MWAITX__"); + if (TARGET_IAMCU) + { + def_or_undef (parse_in, "__iamcu"); + def_or_undef (parse_in, "__iamcu__"); + } } diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 144c1a6fd67..7d26e8c2bd0 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -3433,6 +3433,10 @@ ix86_option_override_internal (bool main_args_p, || TARGET_16BIT_P (opts->x_ix86_isa_flags)) opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_X32; #endif + if (TARGET_64BIT_P (opts->x_ix86_isa_flags) + && TARGET_IAMCU_P (opts->x_target_flags)) + sorry ("Intel MCU psABI isn%'t supported in %s mode", + TARGET_X32_P (opts->x_ix86_isa_flags) ? "x32" : "64-bit"); } #endif @@ -3817,6 +3821,20 @@ ix86_option_override_internal (bool main_args_p, if (TARGET_X32 && (ix86_isa_flags & OPTION_MASK_ISA_MPX)) error ("Intel MPX does not support x32"); + if (TARGET_IAMCU_P (opts->x_target_flags)) + { + /* Verify that x87/MMX/SSE/AVX is off for -miamcu. */ + if (TARGET_80387_P (opts->x_target_flags)) + sorry ("X87 FPU isn%'t supported in Intel MCU psABI"); + else if ((opts->x_ix86_isa_flags & (OPTION_MASK_ISA_MMX + | OPTION_MASK_ISA_SSE + | OPTION_MASK_ISA_AVX))) + sorry ("%s isn%'t supported in Intel MCU psABI", + TARGET_MMX_P (opts->x_ix86_isa_flags) + ? "MMX" + : TARGET_SSE_P (opts->x_ix86_isa_flags) ? "SSE" : "AVX"); + } + if (!strcmp (opts->x_ix86_arch_string, "generic")) error ("generic CPU can be used only for %stune=%s %s", prefix, suffix, sw); @@ -3904,7 +3922,16 @@ ix86_option_override_internal (bool main_args_p, if (opts->x_flag_asynchronous_unwind_tables == 2) opts->x_flag_asynchronous_unwind_tables = !USE_IX86_FRAME_POINTER; if (opts->x_flag_pcc_struct_return == 2) - opts->x_flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN; + { + /* Intel MCU psABI specifies that -freg-struct-return should + be on. Instead of setting DEFAULT_PCC_STRUCT_RETURN to 1, + we check -miamcu so that -freg-struct-return is always + turned on if -miamcu is used. */ + if (TARGET_IAMCU_P (opts->x_target_flags)) + opts->x_flag_pcc_struct_return = 0; + else + opts->x_flag_pcc_struct_return = DEFAULT_PCC_STRUCT_RETURN; + } } ix86_tune_cost = processor_target_table[ix86_tune].cost; @@ -3923,6 +3950,8 @@ ix86_option_override_internal (bool main_args_p, { if (TARGET_64BIT_P (opts->x_ix86_isa_flags)) warning (0, "-mregparm is ignored in 64-bit mode"); + else if (TARGET_IAMCU_P (opts->x_target_flags)) + warning (0, "-mregparm is ignored for Intel MCU psABI"); if (opts->x_ix86_regparm > REGPARM_MAX) { error ("-mregparm=%d is not between 0 and %d", @@ -3930,7 +3959,8 @@ ix86_option_override_internal (bool main_args_p, opts->x_ix86_regparm = 0; } } - if (TARGET_64BIT_P (opts->x_ix86_isa_flags)) + if (TARGET_IAMCU_P (opts->x_target_flags) + || TARGET_64BIT_P (opts->x_ix86_isa_flags)) opts->x_ix86_regparm = REGPARM_MAX; /* Default align_* from the processor table. */ @@ -4334,8 +4364,9 @@ ix86_option_override_internal (bool main_args_p, opts->x_recip_mask &= ~(RECIP_MASK_ALL & ~opts->x_recip_mask_explicit); /* Default long double to 64-bit for 32-bit Bionic and to __float128 - for 64-bit Bionic. */ - if (TARGET_HAS_BIONIC + for 64-bit Bionic. Also default long double to 64-bit for Intel + MCU psABI. */ + if ((TARGET_HAS_BIONIC || TARGET_IAMCU) && !(opts_set->x_target_flags & (MASK_LONG_DOUBLE_64 | MASK_LONG_DOUBLE_128))) opts->x_target_flags |= (TARGET_64BIT @@ -7455,6 +7486,15 @@ function_arg_advance_32 (CUMULATIVE_ARGS *cum, machine_mode mode, int res = 0; bool error_p = NULL; + if (TARGET_IAMCU) + { + /* Intel MCU psABI passes scalars and aggregates no larger than 8 + bytes in registers. */ + if (bytes <= 8) + goto pass_in_reg; + return res; + } + switch (mode) { default: @@ -7469,6 +7509,7 @@ function_arg_advance_32 (CUMULATIVE_ARGS *cum, machine_mode mode, case SImode: case HImode: case QImode: +pass_in_reg: cum->words += words; cum->nregs -= words; cum->regno += words; @@ -7702,6 +7743,15 @@ function_arg_32 (CUMULATIVE_ARGS *cum, machine_mode mode, if (mode == VOIDmode) return constm1_rtx; + if (TARGET_IAMCU) + { + /* Intel MCU psABI passes scalars and aggregates no larger than 8 + bytes in registers. */ + if (bytes <= 8) + goto pass_in_reg; + return NULL_RTX; + } + switch (mode) { default: @@ -7715,6 +7765,7 @@ function_arg_32 (CUMULATIVE_ARGS *cum, machine_mode mode, case SImode: case HImode: case QImode: +pass_in_reg: if (words <= cum->nregs) { int regno = cum->regno; @@ -8561,11 +8612,16 @@ ix86_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) } else { + size = int_size_in_bytes (type); + + /* Intel MCU psABI returns scalars and aggregates no larger than 8 + bytes in registers. */ + if (TARGET_IAMCU) + return size > 8; + if (mode == BLKmode) return true; - size = int_size_in_bytes (type); - if (MS_AGGREGATE_RETURN && AGGREGATE_TYPE_P (type) && size <= 8) return false; @@ -27334,6 +27390,34 @@ ix86_constant_alignment (tree exp, int align) return align; } +/* Compute the alignment for a variable for Intel MCU psABI. TYPE is + the data type, and ALIGN is the alignment that the object would + ordinarily have. */ + +static int +iamcu_alignment (tree type, int align) +{ + enum machine_mode mode; + + if (align < 32 || TYPE_USER_ALIGN (type)) + return align; + + /* Intel MCU psABI specifies scalar types > 4 bytes aligned to 4 + bytes. */ + mode = TYPE_MODE (strip_array_types (type)); + switch (GET_MODE_CLASS (mode)) + { + case MODE_INT: + case MODE_COMPLEX_INT: + case MODE_COMPLEX_FLOAT: + case MODE_FLOAT: + case MODE_DECIMAL_FLOAT: + return 32; + default: + return align; + } +} + /* Compute the alignment for a static variable. TYPE is the data type, and ALIGN is the alignment that the object would ordinarily have. The value of this function is used @@ -27368,6 +27452,9 @@ ix86_data_alignment (tree type, int align, bool opt) case ix86_align_data_type_cacheline: break; } + if (TARGET_IAMCU) + align = iamcu_alignment (type, align); + if (opt && AGGREGATE_TYPE_P (type) && TYPE_SIZE (type) @@ -27477,6 +27564,10 @@ ix86_local_alignment (tree exp, machine_mode mode, return align; } + /* Don't increase alignment for Intel MCU psABI. */ + if (TARGET_IAMCU) + return align; + /* x86-64 ABI requires arrays greater than 16 bytes to be aligned to 16byte boundary. Exact wording is: @@ -43187,6 +43278,8 @@ x86_field_alignment (tree field, int computed) if (TARGET_64BIT || TARGET_ALIGN_DOUBLE) return computed; + if (TARGET_IAMCU) + return iamcu_alignment (type, computed); mode = TYPE_MODE (strip_array_types (type)); if (mode == DFmode || mode == DCmode || GET_MODE_CLASS (mode) == MODE_INT diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index e0af36cec34..d710b3d2643 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -756,7 +756,8 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); /* It should be MIN_STACK_BOUNDARY. But we set it to 128 bits for both 32bit and 64bit, to support codes that need 128 bit stack alignment for SSE instructions, but can't realign the stack. */ -#define PREFERRED_STACK_BOUNDARY_DEFAULT 128 +#define PREFERRED_STACK_BOUNDARY_DEFAULT \ + (TARGET_IAMCU ? MIN_STACK_BOUNDARY : 128) /* 1 if -mstackrealign should be turned on by default. It will generate an alternate prologue and epilogue that realigns the @@ -803,7 +804,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); TARGET_ABSOLUTE_BIGGEST_ALIGNMENT. */ #define BIGGEST_ALIGNMENT \ - (TARGET_AVX512F ? 512 : (TARGET_AVX ? 256 : 128)) + (TARGET_AVX512F ? 512 : (TARGET_AVX ? 256 : (TARGET_IAMCU ? 32 : 128))) /* Maximum stack alignment. */ #define MAX_STACK_ALIGNMENT MAX_OFILE_ALIGNMENT diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index dd46e26de39..042f3c1ab20 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -514,6 +514,10 @@ Clear all tune features mdump-tune-features Target RejectNegative Var(ix86_dump_tunes) Init(0) +miamcu +Target Report Mask(IAMCU) +Generate code that conforms to Intel MCU psABI + mabi= Target RejectNegative Joined Var(ix86_abi) Enum(calling_abi) Init(SYSV_ABI) Generate code that conforms to the given ABI diff --git a/gcc/config/i386/iamcu.h b/gcc/config/i386/iamcu.h new file mode 100644 index 00000000000..a1c83f4dc13 --- /dev/null +++ b/gcc/config/i386/iamcu.h @@ -0,0 +1,42 @@ +/* Definitions of target machine for Intel MCU psABI. + Copyright (C) 2015 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* Intel MCU has no 80387. Default to Intel MCU psABI. */ +#undef TARGET_SUBTARGET_DEFAULT +#define TARGET_SUBTARGET_DEFAULT MASK_IAMCU + +#undef ASM_SPEC +#define ASM_SPEC "--32 -march=iamcu" + +#undef LINK_SPEC +#define LINK_SPEC "-m elf_iamcu" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "" + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "crt0.o%s" + +#undef LIB_SPEC +#define LIB_SPEC "--start-group -lc -lgloss --end-group" diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 02b1493d9d4..0413106deb0 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1096,7 +1096,7 @@ See RS/6000 and PowerPC Options. -mpc32 -mpc64 -mpc80 -mstackrealign @gol -momit-leaf-frame-pointer -mno-red-zone -mno-tls-direct-seg-refs @gol -mcmodel=@var{code-model} -mabi=@var{name} -maddress-mode=@var{mode} @gol --m32 -m64 -mx32 -m16 -mlarge-data-threshold=@var{num} @gol +-m32 -m64 -mx32 -m16 -miamcu -mlarge-data-threshold=@var{num} @gol -msse2avx -mfentry -mrecord-mcount -mnop-mcount -m8bit-idiv @gol -mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol -malign-data=@var{type} -mstack-protector-guard=@var{guard}} @@ -23289,10 +23289,12 @@ on x86-64 processors in 64-bit environments. @itemx -m64 @itemx -mx32 @itemx -m16 +@itemx -miamcu @opindex m32 @opindex m64 @opindex mx32 @opindex m16 +@opindex miamcu Generate code for a 16-bit, 32-bit or 64-bit environment. The @option{-m32} option sets @code{int}, @code{long}, and pointer types to 32 bits, and @@ -23311,6 +23313,9 @@ The @option{-m16} option is the same as @option{-m32}, except for that it outputs the @code{.code16gcc} assembly directive at the beginning of the assembly output so that the binary can run in 16-bit mode. +The @option{-miamcu} option generates code which conforms to Intel MCU +psABI. It requires the @option{-m32} option to be turned on. + @item -mno-red-zone @opindex mno-red-zone Do not use a so-called ``red zone'' for x86-64 code. The red zone is mandated -- 2.30.2