aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJohn David Anglin <danglin@gcc.gnu.org>2023-01-13 19:22:49 +0000
committerJohn David Anglin <danglin@gcc.gnu.org>2023-01-13 19:24:15 +0000
commitcf467fb93b7b92330ddcb9c8fe7c93df45ce8e40 (patch)
tree821c49d285046168caf441f057bb2ab1e499b87c /gcc
parent733a1b777f16cd397b43a242d9c31761f66d3da8 (diff)
downloadgcc-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.h3
-rw-r--r--gcc/config/pa/pa.cc4
-rw-r--r--gcc/config/pa/pa.h12
-rw-r--r--gcc/config/pa/pa.md124
-rw-r--r--gcc/config/pa/pa.opt4
-rw-r--r--gcc/doc/invoke.texi171
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