add the spectre mitigation options for x86:
-mindirect-branch=<choice> -mfunction-return=<choice> -mindirect-branch-register the values for 'choice' are "keep" (default, existing behaviour), "thunk", "thunk-inline", and "thunk-extern". as taken from the Ubuntu port of these changes in their ubuntu:gcc-5_5.5.0-8ubuntu1.diff. i've also included the doc updates that are missing from ubuntu from gcc itself. i've tested both i386 and amd64 fairly heavily with these options enabled in both kernels and userland, atf runs and hundreds of package builds. XXX: pullup-8 to gcc/ not gcc.old/
This commit is contained in:
parent
67e62e9db5
commit
7032fd789a
|
@ -157,12 +157,14 @@
|
|||
|
||||
(define_constraint "Bs"
|
||||
"@internal Sibcall memory operand."
|
||||
(and (not (match_test "TARGET_X32"))
|
||||
(and (not (match_test "ix86_indirect_branch_register"))
|
||||
(not (match_test "TARGET_X32"))
|
||||
(match_operand 0 "sibcall_memory_operand")))
|
||||
|
||||
(define_constraint "Bw"
|
||||
"@internal Call memory operand."
|
||||
(and (not (match_test "TARGET_X32"))
|
||||
(and (not (match_test "ix86_indirect_branch_register"))
|
||||
(not (match_test "TARGET_X32"))
|
||||
(match_operand 0 "memory_operand")))
|
||||
|
||||
(define_constraint "Bz"
|
||||
|
|
|
@ -99,4 +99,17 @@ enum stack_protector_guard {
|
|||
SSP_GLOBAL /* global canary */
|
||||
};
|
||||
|
||||
/* This is used to mitigate variant #2 of the speculative execution
|
||||
vulnerabilities on x86 processors identified by CVE-2017-5715, aka
|
||||
Spectre. They convert indirect branches and function returns to
|
||||
call and return thunks to avoid speculative execution via indirect
|
||||
call, jmp and ret. */
|
||||
enum indirect_branch {
|
||||
indirect_branch_unset = 0,
|
||||
indirect_branch_keep,
|
||||
indirect_branch_thunk,
|
||||
indirect_branch_thunk_inline,
|
||||
indirect_branch_thunk_extern
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -306,6 +306,8 @@ extern enum attr_cpu ix86_schedule;
|
|||
#endif
|
||||
|
||||
extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
|
||||
extern const char * ix86_output_indirect_jmp (rtx call_op, bool ret_p);
|
||||
extern const char * ix86_output_function_return (bool long_p);
|
||||
|
||||
#ifdef RTX_CODE
|
||||
/* Target data for multipass lookahead scheduling.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1210,6 +1210,9 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
|
|||
/* Base register for access to local variables of the function. */
|
||||
#define FRAME_POINTER_REGNUM 20
|
||||
|
||||
#define FIRST_INT_REG AX_REG
|
||||
#define LAST_INT_REG SP_REG
|
||||
|
||||
/* First floating point reg */
|
||||
#define FIRST_FLOAT_REG 8
|
||||
|
||||
|
@ -1446,6 +1449,8 @@ enum reg_class
|
|||
registers. */
|
||||
#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
|
||||
|
||||
#define LEGACY_INT_REGNO_P(N) (IN_RANGE ((N), FIRST_INT_REG, LAST_INT_REG))
|
||||
|
||||
#define QI_REG_P(X) (REG_P (X) && QI_REGNO_P (REGNO (X)))
|
||||
#define QI_REGNO_P(N) IN_RANGE ((N), AX_REG, BX_REG)
|
||||
|
||||
|
@ -2390,9 +2395,56 @@ enum avx_u128_state
|
|||
|
||||
#define FASTCALL_PREFIX '@'
|
||||
|
||||
#ifndef USED_FOR_TARGET
|
||||
/* Structure describing stack frame layout.
|
||||
Stack grows downward:
|
||||
|
||||
[arguments]
|
||||
<- ARG_POINTER
|
||||
saved pc
|
||||
|
||||
saved static chain if ix86_static_chain_on_stack
|
||||
|
||||
saved frame pointer if frame_pointer_needed
|
||||
<- HARD_FRAME_POINTER
|
||||
[saved regs]
|
||||
<- regs_save_offset
|
||||
[padding0]
|
||||
|
||||
[saved SSE regs]
|
||||
<- sse_regs_save_offset
|
||||
[padding1] |
|
||||
| <- FRAME_POINTER
|
||||
[va_arg registers] |
|
||||
|
|
||||
[frame] |
|
||||
|
|
||||
[padding2] | = to_allocate
|
||||
<- STACK_POINTER
|
||||
*/
|
||||
struct GTY(()) ix86_frame
|
||||
{
|
||||
int nsseregs;
|
||||
int nregs;
|
||||
int va_arg_size;
|
||||
int red_zone_size;
|
||||
int outgoing_arguments_size;
|
||||
|
||||
/* The offsets relative to ARG_POINTER. */
|
||||
HOST_WIDE_INT frame_pointer_offset;
|
||||
HOST_WIDE_INT hard_frame_pointer_offset;
|
||||
HOST_WIDE_INT stack_pointer_offset;
|
||||
HOST_WIDE_INT hfp_save_offset;
|
||||
HOST_WIDE_INT reg_save_offset;
|
||||
HOST_WIDE_INT sse_reg_save_offset;
|
||||
|
||||
/* When save_regs_using_mov is set, emit prologue using
|
||||
move instead of push instructions. */
|
||||
bool save_regs_using_mov;
|
||||
};
|
||||
|
||||
/* Machine specific frame tracking during prologue/epilogue generation. */
|
||||
|
||||
#ifndef USED_FOR_TARGET
|
||||
struct GTY(()) machine_frame_state
|
||||
{
|
||||
/* This pair tracks the currently active CFA as reg+offset. When reg
|
||||
|
@ -2438,6 +2490,9 @@ struct GTY(()) machine_function {
|
|||
int varargs_fpr_size;
|
||||
int optimize_mode_switching[MAX_386_ENTITIES];
|
||||
|
||||
/* Cached initial frame layout for the current function. */
|
||||
struct ix86_frame frame;
|
||||
|
||||
/* Number of saved registers USE_FAST_PROLOGUE_EPILOGUE
|
||||
has been computed for. */
|
||||
int use_fast_prologue_epilogue_nregs;
|
||||
|
@ -2481,6 +2536,16 @@ struct GTY(()) machine_function {
|
|||
/* If true, it is safe to not save/restore DRAP register. */
|
||||
BOOL_BITFIELD no_drap_save_restore : 1;
|
||||
|
||||
/* How to generate indirec branch. */
|
||||
ENUM_BITFIELD(indirect_branch) indirect_branch_type : 3;
|
||||
|
||||
/* If true, the current function has local indirect jumps, like
|
||||
"indirect_jump" or "tablejump". */
|
||||
BOOL_BITFIELD has_local_indirect_jump : 1;
|
||||
|
||||
/* How to generate function return. */
|
||||
ENUM_BITFIELD(indirect_branch) function_return_type : 3;
|
||||
|
||||
/* During prologue/epilogue generation, the current frame state.
|
||||
Otherwise, the frame state at the end of the prologue. */
|
||||
struct machine_frame_state fs;
|
||||
|
@ -2505,6 +2570,7 @@ struct GTY(()) machine_function {
|
|||
#define ix86_current_function_calls_tls_descriptor \
|
||||
(ix86_tls_descriptor_calls_expanded_in_cfun && df_regs_ever_live_p (SP_REG))
|
||||
#define ix86_static_chain_on_stack (cfun->machine->static_chain_on_stack)
|
||||
#define ix86_red_zone_size (cfun->machine->frame.red_zone_size)
|
||||
|
||||
/* Control behavior of x86_file_start. */
|
||||
#define X86_FILE_START_VERSION_DIRECTIVE false
|
||||
|
|
|
@ -11585,15 +11585,20 @@
|
|||
[(set (pc) (match_operand 0 "indirect_branch_operand"))]
|
||||
""
|
||||
{
|
||||
if (TARGET_X32)
|
||||
if (TARGET_X32 || ix86_indirect_branch_register)
|
||||
operands[0] = convert_memory_address (word_mode, operands[0]);
|
||||
cfun->machine->has_local_indirect_jump = true;
|
||||
})
|
||||
|
||||
(define_insn "*indirect_jump"
|
||||
[(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))]
|
||||
""
|
||||
"%!jmp\t%A0"
|
||||
[(set_attr "type" "ibr")
|
||||
"* return ix86_output_indirect_jmp (operands[0], false);"
|
||||
[(set (attr "type")
|
||||
(if_then_else (match_test "(cfun->machine->indirect_branch_type
|
||||
!= indirect_branch_keep)")
|
||||
(const_string "multi")
|
||||
(const_string "ibr")))
|
||||
(set_attr "length_immediate" "0")])
|
||||
|
||||
(define_expand "tablejump"
|
||||
|
@ -11633,16 +11638,21 @@
|
|||
OPTAB_DIRECT);
|
||||
}
|
||||
|
||||
if (TARGET_X32)
|
||||
if (TARGET_X32 || ix86_indirect_branch_register)
|
||||
operands[0] = convert_memory_address (word_mode, operands[0]);
|
||||
cfun->machine->has_local_indirect_jump = true;
|
||||
})
|
||||
|
||||
(define_insn "*tablejump_1"
|
||||
[(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))
|
||||
(use (label_ref (match_operand 1)))]
|
||||
""
|
||||
"%!jmp\t%A0"
|
||||
[(set_attr "type" "ibr")
|
||||
"* return ix86_output_indirect_jmp (operands[0], false);"
|
||||
[(set (attr "type")
|
||||
(if_then_else (match_test "(cfun->machine->indirect_branch_type
|
||||
!= indirect_branch_keep)")
|
||||
(const_string "multi")
|
||||
(const_string "ibr")))
|
||||
(set_attr "length_immediate" "0")])
|
||||
|
||||
;; Convert setcc + movzbl to xor + setcc if operands don't overlap.
|
||||
|
@ -11791,7 +11801,7 @@
|
|||
[(call (mem:QI (match_operand:W 0 "memory_operand" "m"))
|
||||
(match_operand 1))
|
||||
(unspec [(const_int 0)] UNSPEC_PEEPSIB)]
|
||||
"!TARGET_X32"
|
||||
"!TARGET_X32 && !ix86_indirect_branch_register"
|
||||
"* return ix86_output_call_insn (insn, operands[0]);"
|
||||
[(set_attr "type" "call")])
|
||||
|
||||
|
@ -11800,7 +11810,9 @@
|
|||
(match_operand:W 1 "memory_operand"))
|
||||
(call (mem:QI (match_dup 0))
|
||||
(match_operand 3))]
|
||||
"!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (1))
|
||||
"!TARGET_X32
|
||||
&& !ix86_indirect_branch_register
|
||||
&& SIBLING_CALL_P (peep2_next_insn (1))
|
||||
&& peep2_reg_dead_p (2, operands[0])"
|
||||
[(parallel [(call (mem:QI (match_dup 1))
|
||||
(match_dup 3))
|
||||
|
@ -11812,7 +11824,9 @@
|
|||
(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)
|
||||
(call (mem:QI (match_dup 0))
|
||||
(match_operand 3))]
|
||||
"!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (2))
|
||||
"!TARGET_X32
|
||||
&& !ix86_indirect_branch_register
|
||||
&& SIBLING_CALL_P (peep2_next_insn (2))
|
||||
&& peep2_reg_dead_p (3, operands[0])"
|
||||
[(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)
|
||||
(parallel [(call (mem:QI (match_dup 1))
|
||||
|
@ -11833,7 +11847,7 @@
|
|||
})
|
||||
|
||||
(define_insn "*call_pop"
|
||||
[(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lmBz"))
|
||||
[(call (mem:QI (match_operand:SI 0 "call_insn_operand" "lBwBz"))
|
||||
(match_operand 1))
|
||||
(set (reg:SI SP_REG)
|
||||
(plus:SI (reg:SI SP_REG)
|
||||
|
@ -11853,7 +11867,7 @@
|
|||
[(set_attr "type" "call")])
|
||||
|
||||
(define_insn "*sibcall_pop_memory"
|
||||
[(call (mem:QI (match_operand:SI 0 "memory_operand" "m"))
|
||||
[(call (mem:QI (match_operand:SI 0 "memory_operand" "Bs"))
|
||||
(match_operand 1))
|
||||
(set (reg:SI SP_REG)
|
||||
(plus:SI (reg:SI SP_REG)
|
||||
|
@ -11905,7 +11919,9 @@
|
|||
[(set (match_operand:W 0 "register_operand")
|
||||
(match_operand:W 1 "memory_operand"))
|
||||
(set (pc) (match_dup 0))]
|
||||
"!TARGET_X32 && peep2_reg_dead_p (2, operands[0])"
|
||||
"!TARGET_X32
|
||||
&& !ix86_indirect_branch_register
|
||||
&& peep2_reg_dead_p (2, operands[0])"
|
||||
[(set (pc) (match_dup 1))])
|
||||
|
||||
;; Call subroutine, returning value in operand 0
|
||||
|
@ -11955,7 +11971,7 @@
|
|||
(call (mem:QI (match_operand:W 1 "memory_operand" "m"))
|
||||
(match_operand 2)))
|
||||
(unspec [(const_int 0)] UNSPEC_PEEPSIB)]
|
||||
"!TARGET_X32"
|
||||
"!TARGET_X32 && !ix86_indirect_branch_register"
|
||||
"* return ix86_output_call_insn (insn, operands[1]);"
|
||||
[(set_attr "type" "callv")])
|
||||
|
||||
|
@ -11965,7 +11981,9 @@
|
|||
(set (match_operand 2)
|
||||
(call (mem:QI (match_dup 0))
|
||||
(match_operand 3)))]
|
||||
"!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (1))
|
||||
"!TARGET_X32
|
||||
&& !ix86_indirect_branch_register
|
||||
&& SIBLING_CALL_P (peep2_next_insn (1))
|
||||
&& peep2_reg_dead_p (2, operands[0])"
|
||||
[(parallel [(set (match_dup 2)
|
||||
(call (mem:QI (match_dup 1))
|
||||
|
@ -11979,7 +11997,9 @@
|
|||
(set (match_operand 2)
|
||||
(call (mem:QI (match_dup 0))
|
||||
(match_operand 3)))]
|
||||
"!TARGET_X32 && SIBLING_CALL_P (peep2_next_insn (2))
|
||||
"!TARGET_X32
|
||||
&& !ix86_indirect_branch_register
|
||||
&& SIBLING_CALL_P (peep2_next_insn (2))
|
||||
&& peep2_reg_dead_p (3, operands[0])"
|
||||
[(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)
|
||||
(parallel [(set (match_dup 2)
|
||||
|
@ -12003,7 +12023,7 @@
|
|||
|
||||
(define_insn "*call_value_pop"
|
||||
[(set (match_operand 0)
|
||||
(call (mem:QI (match_operand:SI 1 "call_insn_operand" "lmBz"))
|
||||
(call (mem:QI (match_operand:SI 1 "call_insn_operand" "lBwBz"))
|
||||
(match_operand 2)))
|
||||
(set (reg:SI SP_REG)
|
||||
(plus:SI (reg:SI SP_REG)
|
||||
|
@ -12196,7 +12216,7 @@
|
|||
(define_insn "simple_return_internal"
|
||||
[(simple_return)]
|
||||
"reload_completed"
|
||||
"%!ret"
|
||||
"* return ix86_output_function_return (false);"
|
||||
[(set_attr "length_nobnd" "1")
|
||||
(set_attr "atom_unit" "jeu")
|
||||
(set_attr "length_immediate" "0")
|
||||
|
@ -12209,12 +12229,7 @@
|
|||
[(simple_return)
|
||||
(unspec [(const_int 0)] UNSPEC_REP)]
|
||||
"reload_completed"
|
||||
{
|
||||
if (ix86_bnd_prefixed_insn_p (insn))
|
||||
return "%!ret";
|
||||
|
||||
return "rep%; ret";
|
||||
}
|
||||
"* return ix86_output_function_return (true);"
|
||||
[(set_attr "length" "2")
|
||||
(set_attr "atom_unit" "jeu")
|
||||
(set_attr "length_immediate" "0")
|
||||
|
@ -12235,8 +12250,12 @@
|
|||
[(simple_return)
|
||||
(use (match_operand:SI 0 "register_operand" "r"))]
|
||||
"reload_completed"
|
||||
"%!jmp\t%A0"
|
||||
[(set_attr "type" "ibr")
|
||||
"* return ix86_output_indirect_jmp (operands[0], true);"
|
||||
[(set (attr "type")
|
||||
(if_then_else (match_test "(cfun->machine->indirect_branch_type
|
||||
!= indirect_branch_keep)")
|
||||
(const_string "multi")
|
||||
(const_string "ibr")))
|
||||
(set_attr "length_immediate" "0")])
|
||||
|
||||
(define_insn "nop"
|
||||
|
|
|
@ -876,3 +876,31 @@ Enum(stack_protector_guard) String(tls) Value(SSP_TLS)
|
|||
|
||||
EnumValue
|
||||
Enum(stack_protector_guard) String(global) Value(SSP_GLOBAL)
|
||||
|
||||
mindirect-branch=
|
||||
Target Report RejectNegative Joined Enum(indirect_branch) Var(ix86_indirect_branch) Init(indirect_branch_keep)
|
||||
Convert indirect call and jump to call and return thunks.
|
||||
|
||||
mfunction-return=
|
||||
Target Report RejectNegative Joined Enum(indirect_branch) Var(ix86_function_return) Init(indirect_branch_keep)
|
||||
Convert function return to call and return thunk.
|
||||
|
||||
Enum
|
||||
Name(indirect_branch) Type(enum indirect_branch)
|
||||
Known indirect branch choices (for use with the -mindirect-branch=/-mfunction-return= options):
|
||||
|
||||
EnumValue
|
||||
Enum(indirect_branch) String(keep) Value(indirect_branch_keep)
|
||||
|
||||
EnumValue
|
||||
Enum(indirect_branch) String(thunk) Value(indirect_branch_thunk)
|
||||
|
||||
EnumValue
|
||||
Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline)
|
||||
|
||||
EnumValue
|
||||
Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern)
|
||||
|
||||
mindirect-branch-register
|
||||
Target Report Var(ix86_indirect_branch_register) Init(0)
|
||||
Force indirect call and jump via register.
|
||||
|
|
|
@ -607,7 +607,8 @@
|
|||
;; Test for a valid operand for indirect branch.
|
||||
(define_predicate "indirect_branch_operand"
|
||||
(ior (match_operand 0 "register_operand")
|
||||
(and (not (match_test "TARGET_X32"))
|
||||
(and (not (match_test "ix86_indirect_branch_register"))
|
||||
(not (match_test "TARGET_X32"))
|
||||
(match_operand 0 "memory_operand"))))
|
||||
|
||||
;; Test for a valid operand for a call instruction.
|
||||
|
@ -616,7 +617,8 @@
|
|||
(ior (match_test "constant_call_address_operand
|
||||
(op, mode == VOIDmode ? mode : Pmode)")
|
||||
(match_operand 0 "call_register_no_elim_operand")
|
||||
(and (not (match_test "TARGET_X32"))
|
||||
(and (not (match_test "ix86_indirect_branch_register"))
|
||||
(not (match_test "TARGET_X32"))
|
||||
(match_operand 0 "memory_operand"))))
|
||||
|
||||
;; Similarly, but for tail calls, in which we cannot allow memory references.
|
||||
|
@ -624,7 +626,8 @@
|
|||
(ior (match_test "constant_call_address_operand
|
||||
(op, mode == VOIDmode ? mode : Pmode)")
|
||||
(match_operand 0 "register_no_elim_operand")
|
||||
(and (not (match_test "TARGET_X32"))
|
||||
(and (not (match_test "ix86_indirect_branch_register"))
|
||||
(not (match_test "TARGET_X32"))
|
||||
(match_operand 0 "sibcall_memory_operand"))))
|
||||
|
||||
;; Match exactly zero.
|
||||
|
|
|
@ -4119,6 +4119,25 @@ Specify which floating-point unit to use. The
|
|||
@code{target("fpmath=sse,387")} option must be specified as
|
||||
@code{target("fpmath=sse+387")} because the comma would separate
|
||||
different options.
|
||||
|
||||
@item indirect_branch("@var{choice}")
|
||||
@cindex @code{indirect_branch} function attribute, x86
|
||||
On x86 targets, the @code{indirect_branch} attribute causes the compiler
|
||||
to convert indirect call and jump with @var{choice}. @samp{keep}
|
||||
keeps indirect call and jump unmodified. @samp{thunk} converts indirect
|
||||
call and jump to call and return thunk. @samp{thunk-inline} converts
|
||||
indirect call and jump to inlined call and return thunk.
|
||||
@samp{thunk-extern} converts indirect call and jump to external call
|
||||
and return thunk provided in a separate object file.
|
||||
|
||||
@item function_return("@var{choice}")
|
||||
@cindex @code{function_return} function attribute, x86
|
||||
On x86 targets, the @code{function_return} attribute causes the compiler
|
||||
to convert function return with @var{choice}. @samp{keep} keeps function
|
||||
return unmodified. @samp{thunk} converts function return to call and
|
||||
return thunk. @samp{thunk-inline} converts function return to inlined
|
||||
call and return thunk. @samp{thunk-extern} converts function return to
|
||||
external call and return thunk provided in a separate object file.
|
||||
@end table
|
||||
|
||||
On the PowerPC, the following options are allowed:
|
||||
|
|
|
@ -23214,6 +23214,42 @@ permits the correct alignment of COMMON variables should be
|
|||
used when generating code. It is enabled by default if
|
||||
GCC detects that the target assembler found during configuration
|
||||
supports the feature.
|
||||
|
||||
@item -mindirect-branch=@var{choice}
|
||||
@opindex -mindirect-branch
|
||||
Convert indirect call and jump with @var{choice}. The default is
|
||||
@samp{keep}, which keeps indirect call and jump unmodified.
|
||||
@samp{thunk} converts indirect call and jump to call and return thunk.
|
||||
@samp{thunk-inline} converts indirect call and jump to inlined call
|
||||
and return thunk. @samp{thunk-extern} converts indirect call and jump
|
||||
to external call and return thunk provided in a separate object file.
|
||||
You can control this behavior for a specific function by using the
|
||||
function attribute @code{indirect_branch}. @xref{Function Attributes}.
|
||||
|
||||
Note that @option{-mcmodel=large} is incompatible with
|
||||
@option{-mindirect-branch=thunk} nor
|
||||
@option{-mindirect-branch=thunk-extern} since the thunk function may
|
||||
not be reachable in large code model.
|
||||
|
||||
@item -mfunction-return=@var{choice}
|
||||
@opindex -mfunction-return
|
||||
Convert function return with @var{choice}. The default is @samp{keep},
|
||||
which keeps function return unmodified. @samp{thunk} converts function
|
||||
return to call and return thunk. @samp{thunk-inline} converts function
|
||||
return to inlined call and return thunk. @samp{thunk-extern} converts
|
||||
function return to external call and return thunk provided in a separate
|
||||
object file. You can control this behavior for a specific function by
|
||||
using the function attribute @code{function_return}.
|
||||
@xref{Function Attributes}.
|
||||
|
||||
Note that @option{-mcmodel=large} is incompatible with
|
||||
@option{-mfunction-return=thunk} nor
|
||||
@option{-mfunction-return=thunk-extern} since the thunk function may
|
||||
not be reachable in large code model.
|
||||
|
||||
@item -mindirect-branch-register
|
||||
@opindex -mindirect-branch-register
|
||||
Force indirect call and jump via register.
|
||||
@end table
|
||||
|
||||
See also under @ref{x86 Options} for standard options.
|
||||
|
|
Loading…
Reference in New Issue