GNU Binutils with patches for OS216
修訂 | 7a77f1ac2c6f899faa39e8c0b42d4284d586c44e (tree) |
---|---|
時間 | 2020-06-16 05:01:30 |
作者 | Max Filippov <jcmvbkbc@gmai...> |
Commiter | Max Filippov |
xtensa: allow runtime ABI selection
2020-06-15 Max Filippov <jcmvbkbc@gmail.com>
bfd/
* elf32-xtensa.c (XSHAL_ABI, XTHAL_ABI_UNDEFINED)
(XTHAL_ABI_WINDOWED, XTHAL_ABI_CALL0): New macros.
(elf32xtensa_abi): New global variable.
(xtensa_abi_choice): New function.
(elf_xtensa_create_plt_entry): Use xtensa_abi_choice instead of
XSHAL_ABI to select PLT code.
gas/
* config/tc-xtensa.c (XTHAL_ABI_WINDOWED, XTHAL_ABI_CALL0): New
macros.
(elf32xtensa_abi): New declaration.
(option_abi_windowed, option_abi_call0): New enum constants.
(md_longopts): Add entries for --abi-windowed and --abi-call0.
(md_parse_option): Add handlers for --abi-windowed and
--abi-call0.
(xtensa_add_config_info): Use xtensa_abi_choice instead of
XSHAL_ABI to format ABI tag.
* doc/as.texi (Target Xtensa options): Add --abi-windowed and
--abi-call0 to the list of options.
* doc/c-xtensa.texi: Add description for options --abi-windowed
and --abi-call0.
* testsuite/gas/xtensa/abi-call0.d: New test definition.
* testsuite/gas/xtensa/abi-windowed.d: New test definition.
* testsuite/gas/xtensa/abi.s: New test source.
include/
* elf/xtensa.h (xtensa_abi_choice): New declaration.
ld/
* emultempl/xtensaelf.em (XSHAL_ABI): Remove macro definition.
(XTHAL_ABI_UNDEFINED, XTHAL_ABI_WINDOWED, XTHAL_ABI_CALL0): New
macros.
(elf32xtensa_abi): New declaration.
(xt_config_info_unpack_and_check): Set elf32xtensa_abi if it is
undefined. Use xtensa_abi_choice instead of XSHAL_ABI to test
ABI tag consistency.
(xtensa_add_config_info): Use xtensa_abi_choice instead of
XSHAL_ABI to format ABI tag.
(PARSE_AND_LIST_PROLOGUE): Define OPTION_ABI_WINDOWED,
OPTION_ABI_CALL0 and declare elf32xtensa_abi.
(PARSE_AND_LIST_LONGOPTS): Add entries for --abi-windowed and
--abi-call0.
(PARSE_AND_LIST_OPTIONS): Add help text for --abi-windowed and
--abi-call0.
(PARSE_AND_LIST_ARGS_CASES): Add handlers for --abi-windowed and
--abi-call0.
* ld.texi: Add description for options --abi-windowed and
--abi-call0.
@@ -1,3 +1,12 @@ | ||
1 | +2020-06-15 Max Filippov <jcmvbkbc@gmail.com> | |
2 | + | |
3 | + * elf32-xtensa.c (XSHAL_ABI, XTHAL_ABI_UNDEFINED) | |
4 | + (XTHAL_ABI_WINDOWED, XTHAL_ABI_CALL0): New macros. | |
5 | + (elf32xtensa_abi): New global variable. | |
6 | + (xtensa_abi_choice): New function. | |
7 | + (elf_xtensa_create_plt_entry): Use xtensa_abi_choice instead of | |
8 | + XSHAL_ABI to select PLT code. | |
9 | + | |
1 | 10 | 2020-06-15 Roland McGrath <mcgrathr@google.com> |
2 | 11 | |
3 | 12 | * elflink.c (bfd_elf_define_start_stop): Use start_stop_visibility |
@@ -37,6 +37,22 @@ | ||
37 | 37 | |
38 | 38 | #define XTENSA_NO_NOP_REMOVAL 0 |
39 | 39 | |
40 | +#ifndef XSHAL_ABI | |
41 | +#define XSHAL_ABI 0 | |
42 | +#endif | |
43 | + | |
44 | +#ifndef XTHAL_ABI_UNDEFINED | |
45 | +#define XTHAL_ABI_UNDEFINED -1 | |
46 | +#endif | |
47 | + | |
48 | +#ifndef XTHAL_ABI_WINDOWED | |
49 | +#define XTHAL_ABI_WINDOWED 0 | |
50 | +#endif | |
51 | + | |
52 | +#ifndef XTHAL_ABI_CALL0 | |
53 | +#define XTHAL_ABI_CALL0 1 | |
54 | +#endif | |
55 | + | |
40 | 56 | /* Local helper functions. */ |
41 | 57 | |
42 | 58 | static bfd_boolean add_extra_plt_sections (struct bfd_link_info *, int); |
@@ -164,6 +180,10 @@ int elf32xtensa_no_literal_movement = 1; | ||
164 | 180 | |
165 | 181 | bfd_boolean elf32xtensa_separate_props = FALSE; |
166 | 182 | |
183 | +/* Xtensa ABI. It affects PLT entry code. */ | |
184 | + | |
185 | +int elf32xtensa_abi = XTHAL_ABI_UNDEFINED; | |
186 | + | |
167 | 187 | /* Rename one of the generic section flags to better document how it |
168 | 188 | is used here. */ |
169 | 189 | /* Whether relocations have been processed. */ |
@@ -2247,6 +2267,13 @@ bfd_elf_xtensa_reloc (bfd *abfd, | ||
2247 | 2267 | return flag; |
2248 | 2268 | } |
2249 | 2269 | |
2270 | +int xtensa_abi_choice (void) | |
2271 | +{ | |
2272 | + if (elf32xtensa_abi == XTHAL_ABI_UNDEFINED) | |
2273 | + return XSHAL_ABI; | |
2274 | + else | |
2275 | + return elf32xtensa_abi; | |
2276 | +} | |
2250 | 2277 | |
2251 | 2278 | /* Set up an entry in the procedure linkage table. */ |
2252 | 2279 |
@@ -2259,6 +2286,7 @@ elf_xtensa_create_plt_entry (struct bfd_link_info *info, | ||
2259 | 2286 | bfd_vma plt_base, got_base; |
2260 | 2287 | bfd_vma code_offset, lit_offset, abi_offset; |
2261 | 2288 | int chunk; |
2289 | + int abi = xtensa_abi_choice (); | |
2262 | 2290 | |
2263 | 2291 | chunk = reloc_index / PLT_ENTRIES_PER_CHUNK; |
2264 | 2292 | splt = elf_xtensa_get_plt_section (info, chunk); |
@@ -2279,10 +2307,10 @@ elf_xtensa_create_plt_entry (struct bfd_link_info *info, | ||
2279 | 2307 | /* Fill in the entry in the procedure linkage table. */ |
2280 | 2308 | memcpy (splt->contents + code_offset, |
2281 | 2309 | (bfd_big_endian (output_bfd) |
2282 | - ? elf_xtensa_be_plt_entry[XSHAL_ABI != XTHAL_ABI_WINDOWED] | |
2283 | - : elf_xtensa_le_plt_entry[XSHAL_ABI != XTHAL_ABI_WINDOWED]), | |
2310 | + ? elf_xtensa_be_plt_entry[abi != XTHAL_ABI_WINDOWED] | |
2311 | + : elf_xtensa_le_plt_entry[abi != XTHAL_ABI_WINDOWED]), | |
2284 | 2312 | PLT_ENTRY_SIZE); |
2285 | - abi_offset = XSHAL_ABI == XTHAL_ABI_WINDOWED ? 3 : 0; | |
2313 | + abi_offset = abi == XTHAL_ABI_WINDOWED ? 3 : 0; | |
2286 | 2314 | bfd_put_16 (output_bfd, l32r_offset (got_base + 0, |
2287 | 2315 | plt_base + code_offset + abi_offset), |
2288 | 2316 | splt->contents + code_offset + abi_offset + 1); |
@@ -1,3 +1,22 @@ | ||
1 | +2020-06-15 Max Filippov <jcmvbkbc@gmail.com> | |
2 | + | |
3 | + * config/tc-xtensa.c (XTHAL_ABI_WINDOWED, XTHAL_ABI_CALL0): New | |
4 | + macros. | |
5 | + (elf32xtensa_abi): New declaration. | |
6 | + (option_abi_windowed, option_abi_call0): New enum constants. | |
7 | + (md_longopts): Add entries for --abi-windowed and --abi-call0. | |
8 | + (md_parse_option): Add handlers for --abi-windowed and | |
9 | + --abi-call0. | |
10 | + (xtensa_add_config_info): Use xtensa_abi_choice instead of | |
11 | + XSHAL_ABI to format ABI tag. | |
12 | + * doc/as.texi (Target Xtensa options): Add --abi-windowed and | |
13 | + --abi-call0 to the list of options. | |
14 | + * doc/c-xtensa.texi: Add description for options --abi-windowed | |
15 | + and --abi-call0. | |
16 | + * testsuite/gas/xtensa/abi-call0.d: New test definition. | |
17 | + * testsuite/gas/xtensa/abi-windowed.d: New test definition. | |
18 | + * testsuite/gas/xtensa/abi.s: New test source. | |
19 | + | |
1 | 20 | 2020-06-14 H.J. Lu <hongjiu.lu@intel.com> |
2 | 21 | |
3 | 22 | PR gas/26115 |
@@ -31,8 +31,12 @@ | ||
31 | 31 | #include "elf/xtensa.h" |
32 | 32 | |
33 | 33 | /* Provide default values for new configuration settings. */ |
34 | -#ifndef XSHAL_ABI | |
35 | -#define XSHAL_ABI 0 | |
34 | +#ifndef XTHAL_ABI_WINDOWED | |
35 | +#define XTHAL_ABI_WINDOWED 0 | |
36 | +#endif | |
37 | + | |
38 | +#ifndef XTHAL_ABI_CALL0 | |
39 | +#define XTHAL_ABI_CALL0 1 | |
36 | 40 | #endif |
37 | 41 | |
38 | 42 | #ifndef XTENSA_MARCH_EARLIEST |
@@ -648,6 +652,10 @@ static bfd_boolean workaround_all_short_loops = FALSE; | ||
648 | 652 | This option is defined in BDF library. */ |
649 | 653 | extern bfd_boolean elf32xtensa_separate_props; |
650 | 654 | |
655 | +/* Xtensa ABI. | |
656 | + This option is defined in BDF library. */ | |
657 | +extern int elf32xtensa_abi; | |
658 | + | |
651 | 659 | static void |
652 | 660 | xtensa_setup_hw_workarounds (int earliest, int latest) |
653 | 661 | { |
@@ -735,6 +743,9 @@ enum | ||
735 | 743 | |
736 | 744 | option_separate_props, |
737 | 745 | option_no_separate_props, |
746 | + | |
747 | + option_abi_windowed, | |
748 | + option_abi_call0, | |
738 | 749 | }; |
739 | 750 | |
740 | 751 | const char *md_shortopts = ""; |
@@ -816,6 +827,9 @@ struct option md_longopts[] = | ||
816 | 827 | |
817 | 828 | { "separate-prop-tables", no_argument, NULL, option_separate_props }, |
818 | 829 | |
830 | + { "abi-windowed", no_argument, NULL, option_abi_windowed }, | |
831 | + { "abi-call0", no_argument, NULL, option_abi_call0 }, | |
832 | + | |
819 | 833 | { NULL, no_argument, NULL, 0 } |
820 | 834 | }; |
821 | 835 |
@@ -1044,6 +1058,14 @@ md_parse_option (int c, const char *arg) | ||
1044 | 1058 | elf32xtensa_separate_props = FALSE; |
1045 | 1059 | return 1; |
1046 | 1060 | |
1061 | + case option_abi_windowed: | |
1062 | + elf32xtensa_abi = XTHAL_ABI_WINDOWED; | |
1063 | + return 1; | |
1064 | + | |
1065 | + case option_abi_call0: | |
1066 | + elf32xtensa_abi = XTHAL_ABI_CALL0; | |
1067 | + return 1; | |
1068 | + | |
1047 | 1069 | default: |
1048 | 1070 | return 0; |
1049 | 1071 | } |
@@ -8958,7 +8980,6 @@ is_local_forward_loop (const TInsn *insn, fragS *fragP) | ||
8958 | 8980 | return FALSE; |
8959 | 8981 | } |
8960 | 8982 | |
8961 | - | |
8962 | 8983 | #define XTINFO_NAME "Xtensa_Info" |
8963 | 8984 | #define XTINFO_NAMESZ 12 |
8964 | 8985 | #define XTINFO_TYPE 1 |
@@ -8975,7 +8996,7 @@ xtensa_add_config_info (void) | ||
8975 | 8996 | |
8976 | 8997 | data = XNEWVEC (char, 100); |
8977 | 8998 | sprintf (data, "USE_ABSOLUTE_LITERALS=%d\nABI=%d\n", |
8978 | - XSHAL_USE_ABSOLUTE_LITERALS, XSHAL_ABI); | |
8999 | + XSHAL_USE_ABSOLUTE_LITERALS, xtensa_abi_choice ()); | |
8979 | 9000 | sz = strlen (data) + 1; |
8980 | 9001 | |
8981 | 9002 | /* Add enough null terminators to pad to a word boundary. */ |
@@ -626,6 +626,7 @@ gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}. | ||
626 | 626 | [@b{--[no-]transform}] |
627 | 627 | [@b{--rename-section} @var{oldname}=@var{newname}] |
628 | 628 | [@b{--[no-]trampolines}] |
629 | + [@b{--abi-windowed}|@b{--abi-call0}] | |
629 | 630 | @end ifset |
630 | 631 | @ifset Z80 |
631 | 632 |
@@ -122,6 +122,14 @@ across a greater range of addresses. @xref{Xtensa Jump Relaxation, | ||
122 | 122 | potentially be out of range. In the absence of such jumps this option |
123 | 123 | does not affect code size or performance. The default is |
124 | 124 | @samp{--trampolines}. |
125 | + | |
126 | +@item --abi-windowed | --abi-call0 | |
127 | +@kindex --abi-windowed | |
128 | +@kindex --abi-call0 | |
129 | +Choose ABI tag written to the @code{.xtensa.info} section. ABI tag | |
130 | +indicates ABI of the assembly code. A warning is issued by the linker | |
131 | +on an attempt to link object files with inconsistent ABI tags. | |
132 | +Default ABI is chosen by the Xtensa core configuration. | |
125 | 133 | @end table |
126 | 134 | |
127 | 135 | @c man end |
@@ -0,0 +1,7 @@ | ||
1 | +#as: --abi-call0 | |
2 | +#objdump: -j .xtensa.info -s | |
3 | +#source: abi.s | |
4 | + | |
5 | +#... | |
6 | +.*ABI=1.* | |
7 | +#... |
@@ -0,0 +1,7 @@ | ||
1 | +#as: --abi-windowed | |
2 | +#objdump: -j .xtensa.info -s | |
3 | +#source: abi.s | |
4 | + | |
5 | +#... | |
6 | +.*ABI=0.* | |
7 | +#... |
@@ -0,0 +1 @@ | ||
1 | + .text |
@@ -1,3 +1,7 @@ | ||
1 | +2020-06-15 Max Filippov <jcmvbkbc@gmail.com> | |
2 | + | |
3 | + * elf/xtensa.h (xtensa_abi_choice): New declaration. | |
4 | + | |
1 | 5 | 2020-06-12 Roland McGrath <mcgrathr@google.com> |
2 | 6 | |
3 | 7 | * bfdlink.h (struct bfd_link_info): New field start_stop_visibility. |
@@ -225,6 +225,9 @@ xtensa_read_table_entries (bfd *abfd, | ||
225 | 225 | extern int |
226 | 226 | xtensa_compute_fill_extra_space (property_table_entry *entry); |
227 | 227 | |
228 | +extern int | |
229 | +xtensa_abi_choice (void); | |
230 | + | |
228 | 231 | #ifdef __cplusplus |
229 | 232 | } |
230 | 233 | #endif |
@@ -1,3 +1,25 @@ | ||
1 | +2020-06-15 Max Filippov <jcmvbkbc@gmail.com> | |
2 | + | |
3 | + * emultempl/xtensaelf.em (XSHAL_ABI): Remove macro definition. | |
4 | + (XTHAL_ABI_UNDEFINED, XTHAL_ABI_WINDOWED, XTHAL_ABI_CALL0): New | |
5 | + macros. | |
6 | + (elf32xtensa_abi): New declaration. | |
7 | + (xt_config_info_unpack_and_check): Set elf32xtensa_abi if it is | |
8 | + undefined. Use xtensa_abi_choice instead of XSHAL_ABI to test | |
9 | + ABI tag consistency. | |
10 | + (xtensa_add_config_info): Use xtensa_abi_choice instead of | |
11 | + XSHAL_ABI to format ABI tag. | |
12 | + (PARSE_AND_LIST_PROLOGUE): Define OPTION_ABI_WINDOWED, | |
13 | + OPTION_ABI_CALL0 and declare elf32xtensa_abi. | |
14 | + (PARSE_AND_LIST_LONGOPTS): Add entries for --abi-windowed and | |
15 | + --abi-call0. | |
16 | + (PARSE_AND_LIST_OPTIONS): Add help text for --abi-windowed and | |
17 | + --abi-call0. | |
18 | + (PARSE_AND_LIST_ARGS_CASES): Add handlers for --abi-windowed and | |
19 | + --abi-call0. | |
20 | + * ld.texi: Add description for options --abi-windowed and | |
21 | + --abi-call0. | |
22 | + | |
1 | 23 | 2020-06-15 Roland McGrath <mcgrathr@google.com> |
2 | 24 | |
3 | 25 | * NEWS: Mention -z start-stop-visibility=... option for ELF. |
@@ -30,8 +30,16 @@ fragment <<EOF | ||
30 | 30 | #include "bfd.h" |
31 | 31 | |
32 | 32 | /* Provide default values for new configuration settings. */ |
33 | -#ifndef XSHAL_ABI | |
34 | -#define XSHAL_ABI 0 | |
33 | +#ifndef XTHAL_ABI_UNDEFINED | |
34 | +#define XTHAL_ABI_UNDEFINED -1 | |
35 | +#endif | |
36 | + | |
37 | +#ifndef XTHAL_ABI_WINDOWED | |
38 | +#define XTHAL_ABI_WINDOWED 0 | |
39 | +#endif | |
40 | + | |
41 | +#ifndef XTHAL_ABI_CALL0 | |
42 | +#define XTHAL_ABI_CALL0 1 | |
35 | 43 | #endif |
36 | 44 | |
37 | 45 | static void xtensa_wild_group_interleave (lang_statement_union_type *); |
@@ -49,6 +57,10 @@ static bfd_boolean xtensa_use_literal_pages = FALSE; | ||
49 | 57 | |
50 | 58 | #define EXTRA_VALIDATION 0 |
51 | 59 | |
60 | +/* Xtensa ABI. | |
61 | + This option is defined in BDF library. */ | |
62 | +extern int elf32xtensa_abi; | |
63 | + | |
52 | 64 | |
53 | 65 | static char * |
54 | 66 | elf_xtensa_choose_target (int argc ATTRIBUTE_UNUSED, |
@@ -306,7 +318,7 @@ xt_config_info_unpack_and_check (char *data, | ||
306 | 318 | char **pmsg) |
307 | 319 | { |
308 | 320 | char *d, *key; |
309 | - unsigned num; | |
321 | + int num; | |
310 | 322 | |
311 | 323 | *pmismatch = FALSE; |
312 | 324 |
@@ -341,7 +353,11 @@ xt_config_info_unpack_and_check (char *data, | ||
341 | 353 | |
342 | 354 | if (! strcmp (key, "ABI")) |
343 | 355 | { |
344 | - if (num != XSHAL_ABI) | |
356 | + if (elf32xtensa_abi == XTHAL_ABI_UNDEFINED) | |
357 | + { | |
358 | + elf32xtensa_abi = num; | |
359 | + } | |
360 | + else if (num != elf32xtensa_abi) | |
345 | 361 | { |
346 | 362 | *pmismatch = TRUE; |
347 | 363 | *pmsg = "ABI does not match"; |
@@ -489,7 +505,7 @@ elf_xtensa_before_allocation (void) | ||
489 | 505 | |
490 | 506 | data = xmalloc (100); |
491 | 507 | sprintf (data, "USE_ABSOLUTE_LITERALS=%d\nABI=%d\n", |
492 | - XSHAL_USE_ABSOLUTE_LITERALS, XSHAL_ABI); | |
508 | + XSHAL_USE_ABSOLUTE_LITERALS, xtensa_abi_choice ()); | |
493 | 509 | xtensa_info_size = strlen (data) + 1; |
494 | 510 | |
495 | 511 | /* Add enough null terminators to pad to a word boundary. */ |
@@ -1920,20 +1936,29 @@ PARSE_AND_LIST_PROLOGUE=' | ||
1920 | 1936 | #define OPTION_OPT_SIZEOPT (300) |
1921 | 1937 | #define OPTION_LITERAL_MOVEMENT (OPTION_OPT_SIZEOPT + 1) |
1922 | 1938 | #define OPTION_NO_LITERAL_MOVEMENT (OPTION_LITERAL_MOVEMENT + 1) |
1939 | +#define OPTION_ABI_WINDOWED (OPTION_NO_LITERAL_MOVEMENT + 1) | |
1940 | +#define OPTION_ABI_CALL0 (OPTION_ABI_WINDOWED + 1) | |
1923 | 1941 | extern int elf32xtensa_size_opt; |
1924 | 1942 | extern int elf32xtensa_no_literal_movement; |
1943 | +extern int elf32xtensa_abi; | |
1925 | 1944 | ' |
1926 | 1945 | |
1927 | 1946 | PARSE_AND_LIST_LONGOPTS=' |
1928 | 1947 | { "size-opt", no_argument, NULL, OPTION_OPT_SIZEOPT}, |
1929 | 1948 | { "literal-movement", no_argument, NULL, OPTION_LITERAL_MOVEMENT}, |
1930 | 1949 | { "no-literal-movement", no_argument, NULL, OPTION_NO_LITERAL_MOVEMENT}, |
1950 | + { "abi-windowed", no_argument, NULL, OPTION_ABI_WINDOWED}, | |
1951 | + { "abi-call0", no_argument, NULL, OPTION_ABI_CALL0}, | |
1931 | 1952 | ' |
1932 | 1953 | |
1933 | 1954 | PARSE_AND_LIST_OPTIONS=' |
1934 | 1955 | fprintf (file, _("\ |
1935 | 1956 | --size-opt When relaxing longcalls, prefer size\n\ |
1936 | 1957 | optimization over branch target alignment\n")); |
1958 | + fprintf (file, _("\ | |
1959 | + --abi-windowed Choose windowed ABI for the output object\n")); | |
1960 | + fprintf (file, _("\ | |
1961 | + --abi-call0 Choose call0 ABI for the output object\n")); | |
1937 | 1962 | ' |
1938 | 1963 | |
1939 | 1964 | PARSE_AND_LIST_ARGS_CASES=' |
@@ -1946,6 +1971,12 @@ PARSE_AND_LIST_ARGS_CASES=' | ||
1946 | 1971 | case OPTION_NO_LITERAL_MOVEMENT: |
1947 | 1972 | elf32xtensa_no_literal_movement = 1; |
1948 | 1973 | break; |
1974 | + case OPTION_ABI_WINDOWED: | |
1975 | + elf32xtensa_abi = XTHAL_ABI_WINDOWED; | |
1976 | + break; | |
1977 | + case OPTION_ABI_CALL0: | |
1978 | + elf32xtensa_abi = XTHAL_ABI_CALL0; | |
1979 | + break; | |
1949 | 1980 | ' |
1950 | 1981 | |
1951 | 1982 | # Replace some of the standard ELF functions with our own versions. |
@@ -8565,6 +8565,17 @@ more than performance. With this option, the linker will not insert | ||
8565 | 8565 | no-ops or widen density instructions to preserve branch target |
8566 | 8566 | alignment. There may still be some cases where no-ops are required to |
8567 | 8567 | preserve the correctness of the code. |
8568 | + | |
8569 | +@item --abi-windowed | |
8570 | +@itemx --abi-call0 | |
8571 | +Choose ABI for the output object and for the generated PLT code. | |
8572 | +PLT code inserted by the linker must match ABI of the output object | |
8573 | +because windowed and call0 ABI use incompatible function call | |
8574 | +conventions. | |
8575 | +Default ABI is chosen by the ABI tag in the @code{.xtensa.info} section | |
8576 | +of the first input object. | |
8577 | +A warning is issued if ABI tags of input objects do not match each other | |
8578 | +or the chosen output object ABI. | |
8568 | 8579 | @end table |
8569 | 8580 | |
8570 | 8581 | @ifclear GENERIC |