diff options
author | John David Anglin <danglin@gcc.gnu.org> | 2023-01-13 19:22:49 +0000 |
---|---|---|
committer | John David Anglin <danglin@gcc.gnu.org> | 2023-01-13 19:24:15 +0000 |
commit | cf467fb93b7b92330ddcb9c8fe7c93df45ce8e40 (patch) | |
tree | 821c49d285046168caf441f057bb2ab1e499b87c /gcc | |
parent | 733a1b777f16cd397b43a242d9c31761f66d3da8 (diff) | |
download | gcc-cf467fb93b7b92330ddcb9c8fe7c93df45ce8e40.zip gcc-cf467fb93b7b92330ddcb9c8fe7c93df45ce8e40.tar.gz gcc-cf467fb93b7b92330ddcb9c8fe7c93df45ce8e40.tar.bz2 |
Fix support for atomic loads and stores on hppa.
This change updates the atomic libcall support to fix the following
issues:
1) A internal compiler error with -fno-sync-libcalls.
2) When sync libcalls are disabled, we don't generate libcalls for
libatomic.
3) There is no sync libcall support for targets other than linux.
As a result, non-atomic stores are silently emitted for types
smaller or equal to the word size. There are now a few atomic
libcalls in the libgcc code, so we need sync support on all
targets.
2023-01-13 John David Anglin <danglin@gcc.gnu.org>
gcc/ChangeLog:
* config/pa/pa-linux.h (TARGET_SYNC_LIBCALL): Delete define.
* config/pa/pa.cc (pa_init_libfuncs): Use MAX_SYNC_LIBFUNC_SIZE
define.
* config/pa/pa.h (TARGET_SYNC_LIBCALLS): Use flag_sync_libcalls.
(MAX_SYNC_LIBFUNC_SIZE): Define.
(TARGET_CPU_CPP_BUILTINS): Define __SOFTFP__ when soft float is
enabled.
* config/pa/pa.md (atomic_storeqi): Emit __atomic_exchange_1
libcall when sync libcalls are disabled.
(atomic_storehi, atomic_storesi, atomic_storedi): Likewise.
(atomic_loaddi): Emit __atomic_load_8 libcall when sync libcalls
are disabled on 32-bit target.
* config/pa/pa.opt (matomic-libcalls): New option.
* doc/invoke.texi (HPPA Options): Update.
libgcc/ChangeLog:
* config.host (hppa*64*-*-linux*): Adjust tmake_file to use
pa/t-pa64-linux.
(hppa*64*-*-hpux11*): Adjust tmake_file to use pa/t-pa64-hpux
instead of pa/t-hpux and pa/t-pa64.
* config/pa/linux-atomic.c: Define u32 type.
(ATOMIC_LOAD): Define new macro to implement atomic_load_1,
atomic_load_2, atomic_load_4 and atomic_load_8. Update sync
defines to use atomic_load calls for type.
(SYNC_LOCK_LOAD_2): New macro to implement __sync_lock_load_8.
* config/pa/sync-libfuncs.c: New file.
* config/pa/t-netbsd (LIB2ADD_ST): Define.
* config/pa/t-openbsd (LIB2ADD_ST): Define.
* config/pa/t-pa64-hpux: New file.
* config/pa/t-pa64-linux: New file.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/pa/pa-linux.h | 3 | ||||
-rw-r--r-- | gcc/config/pa/pa.cc | 4 | ||||
-rw-r--r-- | gcc/config/pa/pa.h | 12 | ||||
-rw-r--r-- | gcc/config/pa/pa.md | 124 | ||||
-rw-r--r-- | gcc/config/pa/pa.opt | 4 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 171 |
6 files changed, 226 insertions, 92 deletions
diff --git a/gcc/config/pa/pa-linux.h b/gcc/config/pa/pa-linux.h index 5af11a1..1073f42 100644 --- a/gcc/config/pa/pa-linux.h +++ b/gcc/config/pa/pa-linux.h @@ -133,9 +133,6 @@ along with GCC; see the file COPYING3. If not see #undef TARGET_GAS #define TARGET_GAS 1 -#undef TARGET_SYNC_LIBCALL -#define TARGET_SYNC_LIBCALL 1 - /* The SYNC operations are implemented as library functions, not INSN patterns. As a result, the HAVE defines for the patterns are not defined. We need to define them to generate the corresponding diff --git a/gcc/config/pa/pa.cc b/gcc/config/pa/pa.cc index 9f43802..b43a91f 100644 --- a/gcc/config/pa/pa.cc +++ b/gcc/config/pa/pa.cc @@ -5940,8 +5940,8 @@ pa_init_libfuncs (void) "_U_Qfcnvxf_udbl_to_quad"); } - if (TARGET_SYNC_LIBCALL) - init_sync_libfuncs (8); + if (TARGET_SYNC_LIBCALLS) + init_sync_libfuncs (MAX_SYNC_LIBFUNC_SIZE); } /* HP's millicode routines mean something special to the assembler. diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index bafdf60..93d6f53 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -72,10 +72,12 @@ extern unsigned long total_code_bytes; #define HPUX_LONG_DOUBLE_LIBRARY 0 #endif -/* Linux kernel atomic operation support. */ -#ifndef TARGET_SYNC_LIBCALL -#define TARGET_SYNC_LIBCALL 0 -#endif +/* Sync libcall support. */ +#define TARGET_SYNC_LIBCALLS (flag_sync_libcalls) + +/* The maximum size of the sync library functions supported. DImode + is supported on 32-bit targets using floating point loads and stores. */ +#define MAX_SYNC_LIBFUNC_SIZE 8 /* The following three defines are potential target switches. The current defines are optimal given the current capabilities of GAS and GNU ld. */ @@ -173,6 +175,8 @@ do { \ builtin_define("_PA_RISC1_0"); \ if (HPUX_LONG_DOUBLE_LIBRARY) \ builtin_define("__SIZEOF_FLOAT128__=16"); \ + if (TARGET_SOFT_FLOAT) \ + builtin_define("__SOFTFP__"); \ } while (0) /* An old set of OS defines for various BSD-like systems. */ diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index 4138227..71f391f 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -10360,7 +10360,23 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" ;; doubleword loads and stores are not guaranteed to be atomic ;; when referencing the I/O address space. -;; These patterns are at the bottom so the non atomic versions are preferred. +;; Atomic and sync libcalls use different lock sets. Great care is +;; needed if both are used in a single application. + +;; Atomic load and store libcalls are enabled by the -matomic-libcalls +;; option. This option is not enabled by default as the generated +;; libcalls depend on libatomic which is not built until the end of +;; the gcc build. For loads, we only need an atomic libcall for DImode. +;; Sync libcalls are not generated when atomic libcalls are enabled. + +;; Sync libcalls are enabled by default when supported. They can be +;; disabled by the -fno-sync-libcalls option. Sync libcalls always +;; use a single memory store in their implementation, even for DImode. +;; DImode stores are done using either std or fstd. Thus, we only +;; need a sync load libcall for DImode when we don't have an atomic +;; processor load available for the mode (TARGET_SOFT_FLOAT). + +;; Implement atomic QImode store using exchange. (define_expand "atomic_storeqi" [(match_operand:QI 0 "memory_operand") ;; memory @@ -10368,19 +10384,30 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" (match_operand:SI 2 "const_int_operand")] ;; model "" { - if (TARGET_SYNC_LIBCALL) + rtx addr, libfunc; + + if (TARGET_SYNC_LIBCALLS) { - rtx libfunc = optab_libfunc (sync_lock_test_and_set_optab, QImode); - rtx addr = convert_memory_address (Pmode, XEXP (operands[0], 0)); + addr = convert_memory_address (Pmode, XEXP (operands[0], 0)); + libfunc = optab_libfunc (sync_lock_test_and_set_optab, QImode); + emit_library_call (libfunc, LCT_NORMAL, VOIDmode, addr, Pmode, + operands[1], QImode); + DONE; + } + if (TARGET_ATOMIC_LIBCALLS) + { + addr = convert_memory_address (Pmode, XEXP (operands[0], 0)); + libfunc = init_one_libfunc ("__atomic_exchange_1"); emit_library_call (libfunc, LCT_NORMAL, VOIDmode, addr, Pmode, operands[1], QImode); DONE; } + FAIL; }) -;; Implement atomic HImode stores using exchange. +;; Implement atomic HImode store using exchange. (define_expand "atomic_storehi" [(match_operand:HI 0 "memory_operand") ;; memory @@ -10388,15 +10415,26 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" (match_operand:SI 2 "const_int_operand")] ;; model "" { - if (TARGET_SYNC_LIBCALL) + rtx addr, libfunc; + + if (TARGET_SYNC_LIBCALLS) { - rtx libfunc = optab_libfunc (sync_lock_test_and_set_optab, HImode); - rtx addr = convert_memory_address (Pmode, XEXP (operands[0], 0)); + addr = convert_memory_address (Pmode, XEXP (operands[0], 0)); + libfunc = optab_libfunc (sync_lock_test_and_set_optab, HImode); + emit_library_call (libfunc, LCT_NORMAL, VOIDmode, addr, Pmode, + operands[1], HImode); + DONE; + } + if (TARGET_ATOMIC_LIBCALLS) + { + addr = convert_memory_address (Pmode, XEXP (operands[0], 0)); + libfunc = init_one_libfunc ("__atomic_exchange_2"); emit_library_call (libfunc, LCT_NORMAL, VOIDmode, addr, Pmode, operands[1], HImode); DONE; } + FAIL; }) @@ -10408,20 +10446,39 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" (match_operand:SI 2 "const_int_operand")] ;; model "" { - if (TARGET_SYNC_LIBCALL) + rtx addr, libfunc; + + if (TARGET_SYNC_LIBCALLS) { - rtx libfunc = optab_libfunc (sync_lock_test_and_set_optab, SImode); - rtx addr = convert_memory_address (Pmode, XEXP (operands[0], 0)); + addr = convert_memory_address (Pmode, XEXP (operands[0], 0)); + libfunc = optab_libfunc (sync_lock_test_and_set_optab, SImode); + emit_library_call (libfunc, LCT_NORMAL, VOIDmode, addr, Pmode, + operands[1], SImode); + DONE; + } + if (TARGET_ATOMIC_LIBCALLS) + { + addr = convert_memory_address (Pmode, XEXP (operands[0], 0)); + libfunc = init_one_libfunc ("__atomic_exchange_4"); emit_library_call (libfunc, LCT_NORMAL, VOIDmode, addr, Pmode, operands[1], SImode); DONE; } + FAIL; }) ;; Implement atomic DImode load. +;; We need an atomic or sync libcall whenever the processor load or +;; store used for DImode is not atomic. The 32-bit libatomic +;; implementation uses a pair of stw instructions. They are not +;; atomic, so we need to call __atomic_load_8. The linux libgcc +;; sync implementation uses a std or fstd instruction. They are +;; atomic, so we only need to call __sync_load_8 when the load +;; operation would not be atomic (e.g., 32-bit TARGET_SOFT_FLOAT). + (define_expand "atomic_loaddi" [(match_operand:DI 0 "register_operand") ;; val out (match_operand:DI 1 "memory_operand") ;; memory @@ -10429,12 +10486,35 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" "" { enum memmodel model; + rtx addr, libfunc; - if (TARGET_64BIT || TARGET_SOFT_FLOAT) + if (TARGET_64BIT) FAIL; + if (TARGET_SYNC_LIBCALLS && MAX_SYNC_LIBFUNC_SIZE >= 8 && TARGET_SOFT_FLOAT) + { + addr = convert_memory_address (Pmode, XEXP (operands[1], 0)); + libfunc = init_one_libfunc ("__sync_load_8"); + emit_library_call_value (libfunc, operands[0], LCT_NORMAL, DImode, + addr, Pmode); + DONE; + } + + if (TARGET_ATOMIC_LIBCALLS && TARGET_SOFT_FLOAT) + { + addr = convert_memory_address (Pmode, XEXP (operands[1], 0)); + libfunc = init_one_libfunc ("__atomic_load_8"); + emit_library_call_value (libfunc, operands[0], LCT_NORMAL, DImode, + addr, Pmode); + DONE; + } + + if (TARGET_SOFT_FLOAT) + FAIL; + + /* Fallback to processor load with barriers. */ model = memmodel_from_int (INTVAL (operands[2])); - operands[1] = force_reg (SImode, XEXP (operands[1], 0)); + operands[1] = force_reg (Pmode, XEXP (operands[1], 0)); if (is_mm_seq_cst (model)) expand_mem_thread_fence (model); emit_insn (gen_atomic_loaddi_1 (operands[0], operands[1])); @@ -10460,12 +10540,21 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" "" { enum memmodel model; + rtx addr, libfunc; - if (TARGET_SYNC_LIBCALL) + if (TARGET_SYNC_LIBCALLS && MAX_SYNC_LIBFUNC_SIZE >= 8) { - rtx libfunc = optab_libfunc (sync_lock_test_and_set_optab, DImode); - rtx addr = convert_memory_address (Pmode, XEXP (operands[0], 0)); + addr = convert_memory_address (Pmode, XEXP (operands[0], 0)); + libfunc = optab_libfunc (sync_lock_test_and_set_optab, DImode); + emit_library_call (libfunc, LCT_NORMAL, VOIDmode, addr, Pmode, + operands[1], DImode); + DONE; + } + if (TARGET_ATOMIC_LIBCALLS) + { + addr = convert_memory_address (Pmode, XEXP (operands[0], 0)); + libfunc = init_one_libfunc ("__atomic_exchange_8"); emit_library_call (libfunc, LCT_NORMAL, VOIDmode, addr, Pmode, operands[1], DImode); DONE; @@ -10474,8 +10563,9 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" if (TARGET_64BIT || TARGET_SOFT_FLOAT) FAIL; + /* Fallback to processor store with barriers. */ model = memmodel_from_int (INTVAL (operands[2])); - operands[0] = force_reg (SImode, XEXP (operands[0], 0)); + operands[0] = force_reg (Pmode, XEXP (operands[0], 0)); if (operands[1] != CONST0_RTX (DImode)) operands[1] = force_reg (DImode, operands[1]); expand_mem_thread_fence (model); diff --git a/gcc/config/pa/pa.opt b/gcc/config/pa/pa.opt index 58b59f8..2d074f5 100644 --- a/gcc/config/pa/pa.opt +++ b/gcc/config/pa/pa.opt @@ -37,6 +37,10 @@ march=2.0 Target RejectNegative Generate PA2.0 code (requires binutils 2.10 or later). +matomic-libcalls +Target Var(TARGET_ATOMIC_LIBCALLS) Init(1) +Generate libcalls for atomic loads and stores when sync libcalls are disabled. + mbig-switch Target Ignore Does nothing. Preserved for backward compatibility. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 0b0bdb6..dec0cdb 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -975,17 +975,18 @@ Objective-C and Objective-C++ Dialects}. @emph{HPPA Options} @gccoptlist{-march=@var{architecture-type} @gol +-matomic-libcalls -mbig-switch @gol -mcaller-copies -mdisable-fpregs -mdisable-indexing @gol --mfast-indirect-calls -mgas -mgnu-ld -mhp-ld @gol +-mordered -mfast-indirect-calls -mgas -mgnu-ld -mhp-ld @gol -mfixed-range=@var{register-range} @gol --mjump-in-delay -mlinker-opt -mlong-calls @gol --mlong-load-store -mno-disable-fpregs @gol +-mcoherent-ldcw -mjump-in-delay -mlinker-opt -mlong-calls @gol +-mlong-load-store -mno-atomic-libcalls -mno-disable-fpregs @gol -mno-disable-indexing -mno-fast-indirect-calls -mno-gas @gol -mno-jump-in-delay -mno-long-load-store @gol -mno-portable-runtime -mno-soft-float @gol -mno-space-regs -msoft-float -mpa-risc-1-0 @gol -mpa-risc-1-1 -mpa-risc-2-0 -mportable-runtime @gol --mschedule=@var{cpu-type} -mspace-regs -msio -mwsio @gol +-mschedule=@var{cpu-type} -mspace-regs -msoft-mult -msio -mwsio @gol -munix=@var{unix-std} -nolibdld -static -threads} @emph{IA-64 Options} @@ -24895,6 +24896,33 @@ other way around. @opindex mpa-risc-2-0 Synonyms for @option{-march=1.0}, @option{-march=1.1}, and @option{-march=2.0} respectively. +@item -matomic-libcalls +@opindex matomic-libcalls +@opindex mno-atomic-libcalls +Generate libcalls for atomic loads and stores when sync libcalls are disabled. +This option is enabled by default. It only affects the generation of +atomic libcalls by the HPPA backend. + +Both the sync and @file{libatomic} libcall implementations use locking. +As a result, processor stores are not atomic with respect to other +atomic operations. Processor loads up to DImode are atomic with +respect to other atomic operations provided they are implemented as +a single access. + +The PA-RISC architecture does not support any atomic operations in +hardware except for the @code{ldcw} instruction. Thus, all atomic +support is implemented using sync and atomic libcalls. Sync libcall +support is in @file{libgcc.a}. Atomic libcall support is in +@file{libatomic}. + +This option generates @code{__atomic_exchange} calls for atomic stores. +It also provides special handling for atomic DImode accesses on 32-bit +targets. + +@item -mbig-switch +@opindex mbig-switch +Does nothing. Preserved for backward compatibility. + @item -mcaller-copies @opindex mcaller-copies The caller copies function arguments passed by hidden reference. This @@ -24903,30 +24931,19 @@ option should be used with care as it is not compatible with the default passed by hidden reference and the option provides better compatibility with OpenMP. -@item -mjump-in-delay -@opindex mjump-in-delay -This option is ignored and provided for compatibility purposes only. +@item -mcoherent-ldcw +@opindex mcoherent-ldcw +Use ldcw/ldcd coherent cache-control hint. @item -mdisable-fpregs @opindex mdisable-fpregs -Prevent floating-point registers from being used in any manner. This is -necessary for compiling kernels that perform lazy context switching of -floating-point registers. If you use this option and attempt to perform -floating-point operations, the compiler aborts. +Disable floating-point registers. Equivalent to @code{-msoft-float}. @item -mdisable-indexing @opindex mdisable-indexing Prevent the compiler from using indexing address modes. This avoids some rather obscure problems when compiling MIG generated code under MACH@. -@item -mno-space-regs -@opindex mno-space-regs -@opindex mspace-regs -Generate code that assumes the target has no space registers. This allows -GCC to generate faster indirect calls and use unscaled index address modes. - -Such code is suitable for level 0 PA systems and kernels. - @item -mfast-indirect-calls @opindex mfast-indirect-calls Generate code that assumes calls never cross space boundaries. This @@ -24943,57 +24960,10 @@ useful when compiling kernel code. A register range is specified as two registers separated by a dash. Multiple register ranges can be specified separated by a comma. -@item -mlong-load-store -@opindex mlong-load-store -Generate 3-instruction load and store sequences as sometimes required by -the HP-UX 10 linker. This is equivalent to the @samp{+k} option to -the HP compilers. - -@item -mportable-runtime -@opindex mportable-runtime -Use the portable calling conventions proposed by HP for ELF systems. - @item -mgas @opindex mgas Enable the use of assembler directives only GAS understands. -@item -mschedule=@var{cpu-type} -@opindex mschedule -Schedule code according to the constraints for the machine type -@var{cpu-type}. The choices for @var{cpu-type} are @samp{700} -@samp{7100}, @samp{7100LC}, @samp{7200}, @samp{7300} and @samp{8000}. Refer -to @file{/usr/lib/sched.models} on an HP-UX system to determine the -proper scheduling option for your machine. The default scheduling is -@samp{8000}. - -@item -mlinker-opt -@opindex mlinker-opt -Enable the optimization pass in the HP-UX linker. Note this makes symbolic -debugging impossible. It also triggers a bug in the HP-UX 8 and HP-UX 9 -linkers in which they give bogus error messages when linking some programs. - -@item -msoft-float -@opindex msoft-float -Generate output containing library calls for floating point. -@strong{Warning:} the requisite libraries are not available for all HPPA -targets. Normally the facilities of the machine's usual C compiler are -used, but this cannot be done directly in cross-compilation. You must make -your own arrangements to provide suitable library functions for -cross-compilation. - -@option{-msoft-float} changes the calling convention in the output file; -therefore, it is only useful if you compile @emph{all} of a program with -this option. In particular, you need to compile @file{libgcc.a}, the -library that comes with GCC, with @option{-msoft-float} in order for -this to work. - -@item -msio -@opindex msio -Generate the predefine, @code{_SIO}, for server IO@. The default is -@option{-mwsio}. This generates the predefines, @code{__hp9000s700}, -@code{__hp9000s700__} and @code{_WSIO}, for workstation IO@. These -options are available under HP-UX and HI-UX@. - @item -mgnu-ld @opindex mgnu-ld Use options specific to GNU @command{ld}. @@ -25023,6 +24993,12 @@ configure option, GCC's program search path, and finally by the user's `gcc -print-prog-name=ld`}. This option is only available on the 64-bit HP-UX GCC, i.e.@: configured with @samp{hppa*64*-*-hpux*}. +@item -mlinker-opt +@opindex mlinker-opt +Enable the optimization pass in the HP-UX linker. Note this makes symbolic +debugging impossible. It also triggers a bug in the HP-UX 8 and HP-UX 9 +linkers in which they give bogus error messages when linking some programs. + @item -mlong-calls @opindex mno-long-calls @opindex mlong-calls @@ -25051,6 +25027,69 @@ symbol-difference or pc-relative calls should be relatively small. However, an indirect call is used on 32-bit ELF systems in pic code and it is quite long. +@item -mlong-load-store +@opindex mlong-load-store +Generate 3-instruction load and store sequences as sometimes required by +the HP-UX 10 linker. This is equivalent to the @samp{+k} option to +the HP compilers. + +@item -mjump-in-delay +@opindex mjump-in-delay +This option is ignored and provided for compatibility purposes only. + +@item -mno-space-regs +@opindex mno-space-regs +@opindex mspace-regs +Generate code that assumes the target has no space registers. This allows +GCC to generate faster indirect calls and use unscaled index address modes. + +Such code is suitable for level 0 PA systems and kernels. + +@item -mordered +@opindex mordered +Assume memory references are ordered and barriers are not needed. + +@item -mportable-runtime +@opindex mportable-runtime +Use the portable calling conventions proposed by HP for ELF systems. + +@item -mschedule=@var{cpu-type} +@opindex mschedule +Schedule code according to the constraints for the machine type +@var{cpu-type}. The choices for @var{cpu-type} are @samp{700} +@samp{7100}, @samp{7100LC}, @samp{7200}, @samp{7300} and @samp{8000}. Refer +to @file{/usr/lib/sched.models} on an HP-UX system to determine the +proper scheduling option for your machine. The default scheduling is +@samp{8000}. + +@item -msio +@opindex msio +Generate the predefine, @code{_SIO}, for server IO@. The default is +@option{-mwsio}. This generates the predefines, @code{__hp9000s700}, +@code{__hp9000s700__} and @code{_WSIO}, for workstation IO@. These +options are available under HP-UX and HI-UX@. + +@item -msoft-float +@opindex msoft-float +Generate output containing library calls for floating point. +@strong{Warning:} the requisite libraries are not available for all HPPA +targets. Normally the facilities of the machine's usual C compiler are +used, but this cannot be done directly in cross-compilation. You must make +your own arrangements to provide suitable library functions for +cross-compilation. + +@option{-msoft-float} changes the calling convention in the output file; +therefore, it is only useful if you compile @emph{all} of a program with +this option. In particular, you need to compile @file{libgcc.a}, the +library that comes with GCC, with @option{-msoft-float} in order for +this to work. + +@item -msoft-mult +@opindex msoft-mult +Use software integer multiplication. + +This disables the use of the @code{xmpyu} instruction. + @item -munix=@var{unix-std} @opindex march Generate compiler predefines and select a startfile for the specified |