aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorIlya Enkovich <ilya.enkovich@intel.com>2013-10-25 05:37:57 +0000
committerKirill Yukhin <kyukhin@gcc.gnu.org>2013-10-25 05:37:57 +0000
commit66d6cbaa5612d12933f42472a2ee93de920fb1d2 (patch)
tree1b27bbb3edda5c779a77ecbab7f71a5dde4ae3df /gcc/config
parent65f55baca45eab3a999918e37c3853f5cc8ab3ae (diff)
downloadgcc-66d6cbaa5612d12933f42472a2ee93de920fb1d2.zip
gcc-66d6cbaa5612d12933f42472a2ee93de920fb1d2.tar.gz
gcc-66d6cbaa5612d12933f42472a2ee93de920fb1d2.tar.bz2
constraints.md (B): New.
* config/i386/constraints.md (B): New. (Ti): New. (Tb): New. * config/i386/i386-c.c (ix86_target_macros_internal): Add __MPX__. * config/i386/i386-modes.def (BND32): New. (BND64): New. * config/i386/i386-protos.h (ix86_bnd_prefixed_insn_p): New. * config/i386/i386.c (isa_opts): Add mmpx. (regclass_map): Add bound registers. (dbx_register_map): Likewise. (dbx64_register_map): Likewise. (svr4_dbx_register_map): Likewise. (PTA_MPX): New. (ix86_option_override_internal): Support MPX ISA. (ix86_conditional_register_usage): Support bound registers. (print_reg): Likewise. (ix86_code_end): Add MPX bnd prefix. (output_set_got): Likewise. (ix86_output_call_insn): Likewise. (ix86_print_operand): Add '!' (MPX bnd) print prefix support. (ix86_print_operand_punct_valid_p): Likewise. (ix86_print_operand_address): Support UNSPEC_BNDMK_ADDR and UNSPEC_BNDMK_ADDR. (ix86_class_likely_spilled_p): Add bound regs support. (ix86_hard_regno_mode_ok): Likewise. (x86_order_regs_for_local_alloc): Likewise. (ix86_bnd_prefixed_insn_p): New. * config/i386/i386.h (FIRST_PSEUDO_REGISTER): Fix to new value. (FIXED_REGISTERS): Add bound registers. (CALL_USED_REGISTERS): Likewise. (REG_ALLOC_ORDER): Likewise. (HARD_REGNO_NREGS): Likewise. (TARGET_MPX): New. (VALID_BND_REG_MODE): New. (FIRST_BND_REG): New. (LAST_BND_REG): New. (reg_class): Add BND_REGS. (REG_CLASS_NAMES): Likewise. (REG_CLASS_CONTENTS): Likewise. (BND_REGNO_P): New. (ANY_BND_REG_P): New. (BNDmode): New. (HI_REGISTER_NAMES): Add bound registers. * config/i386/i386.md (UNSPEC_BNDMK): New. (UNSPEC_BNDMK_ADDR): New. (UNSPEC_BNDSTX): New. (UNSPEC_BNDLDX): New. (UNSPEC_BNDLDX_ADDR): New. (UNSPEC_BNDCL): New. (UNSPEC_BNDCU): New. (UNSPEC_BNDCN): New. (UNSPEC_MPX_FENCE): New. (BND0_REG): New. (BND1_REG): New. (type): Add mpxmov, mpxmk, mpxchk, mpxld, mpxst. (length_immediate): Likewise. (prefix_0f): Likewise. (memory): Likewise. (prefix_rep): Check for bnd prefix. (length_nobnd): New. (length): Use length_nobnd if specified. (BND): New. (bnd_ptr): New. (BNDCHECK): New. (bndcheck): New. (*jcc_1): Add bnd prefix and rename length attr to length_nobnd. (*jcc_2): Likewise. (jump): Likewise. (simple_return_internal): Likewise. (simple_return_pop_internal): Likewise. (*indirect_jump): Add MPX bnd prefix. (*tablejump_1): Likewise. (simple_return_internal_long): Likewise. (simple_return_indirect_internal): Likewise. (<mode>_mk): New. (*<mode>_mk): New. (mov<mode>): New. (*mov<mode>_internal_mpx): New. (<mode>_<bndcheck>): New. (*<mode>_<bndcheck>): New. (<mode>_ldx): New. (*<mode>_ldx): New. (<mode>_stx): New. (*<mode>_stx): New. * config/i386/predicates.md (lea_address_operand): Rename to... (address_no_seg_operand): ... this. (address_mpx_no_base_operand): New. (address_mpx_no_index_operand): New. (bnd_mem_operator): New. * config/i386/i386.opt (mmpx): New. * doc/invoke.texi: Add documentation for the flags -mmpx, -mno-mpx. * doc/rtl.texi Add documentation for BND32mode and BND64mode. From-SVN: r204046
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/i386/constraints.md17
-rw-r--r--gcc/config/i386/i386-c.c2
-rw-r--r--gcc/config/i386/i386-modes.def3
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c74
-rw-r--r--gcc/config/i386/i386.h94
-rw-r--r--gcc/config/i386/i386.md217
-rw-r--r--gcc/config/i386/i386.opt4
-rw-r--r--gcc/config/i386/predicates.md67
9 files changed, 412 insertions, 68 deletions
diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index 92e0c05..ddfd402 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -18,7 +18,7 @@
;; <http://www.gnu.org/licenses/>.
;;; Unused letters:
-;;; B H T
+;;; H
;;; h j
;; Integer register constraints.
@@ -91,6 +91,9 @@
(define_register_constraint "x" "TARGET_SSE ? SSE_REGS : NO_REGS"
"Any SSE register.")
+(define_register_constraint "B" "TARGET_MPX ? BND_REGS : NO_REGS"
+ "@internal Any bound register.")
+
;; We use the Y prefix to denote any number of conditional register sets:
;; z First SSE register.
;; i SSE2 inter-unit moves to SSE register enabled
@@ -232,3 +235,15 @@
to fit that range (for immediate operands in zero-extending x86-64
instructions)."
(match_operand 0 "x86_64_zext_immediate_operand"))
+
+;; T prefix is used for different address constraints
+;; i - address with no index and no rip
+;; b - address with no base and no rip
+
+(define_address_constraint "Ti"
+ "MPX address operand without index"
+ (match_operand 0 "address_mpx_no_index_operand"))
+
+(define_address_constraint "Tb"
+ "MPX address operand without base"
+ (match_operand 0 "address_mpx_no_base_operand"))
diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c
index 8a41fb0..a6eaf8a 100644
--- a/gcc/config/i386/i386-c.c
+++ b/gcc/config/i386/i386-c.c
@@ -358,6 +358,8 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
def_or_undef (parse_in, "__SSE_MATH__");
if ((fpmath & FPMATH_SSE) && (isa_flag & OPTION_MASK_ISA_SSE2))
def_or_undef (parse_in, "__SSE2_MATH__");
+ if (isa_flag & OPTION_MASK_ISA_MPX)
+ def_or_undef (parse_in, "__MPX__");
}
diff --git a/gcc/config/i386/i386-modes.def b/gcc/config/i386/i386-modes.def
index e0b8fc8..a73730e 100644
--- a/gcc/config/i386/i386-modes.def
+++ b/gcc/config/i386/i386-modes.def
@@ -87,6 +87,9 @@ VECTOR_MODE (INT, DI, 1); /* V1DI */
VECTOR_MODE (INT, SI, 1); /* V1SI */
VECTOR_MODE (INT, QI, 2); /* V2QI */
+POINTER_BOUNDS_MODE (BND32, 8);
+POINTER_BOUNDS_MODE (BND64, 16);
+
INT_MODE (OI, 32);
INT_MODE (XI, 64);
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index df38876..b1d014a 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -241,6 +241,8 @@ extern void ix86_expand_mul_widen_hilo (rtx, rtx, rtx, bool, bool);
extern void ix86_expand_sse2_mulv4si3 (rtx, rtx, rtx);
extern void ix86_expand_sse2_mulvxdi3 (rtx, rtx, rtx);
+extern bool ix86_bnd_prefixed_insn_p (rtx);
+
/* In i386-c.c */
extern void ix86_target_macros (void);
extern void ix86_register_pragmas (void);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 25c63c7..4a185bf 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -1943,6 +1943,8 @@ enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER] =
/* Mask registers. */
MASK_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS,
MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS,
+ /* MPX bound registers */
+ BND_REGS, BND_REGS, BND_REGS, BND_REGS,
};
/* The "default" register map used in 32bit mode. */
@@ -1959,6 +1961,7 @@ int const dbx_register_map[FIRST_PSEUDO_REGISTER] =
-1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 16-23*/
-1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 24-31*/
93, 94, 95, 96, 97, 98, 99, 100, /* Mask registers */
+ 101, 102, 103, 104, /* bound registers */
};
/* The "default" register map used in 64bit mode. */
@@ -1975,6 +1978,7 @@ int const dbx64_register_map[FIRST_PSEUDO_REGISTER] =
67, 68, 69, 70, 71, 72, 73, 74, /* AVX-512 registers 16-23 */
75, 76, 77, 78, 79, 80, 81, 82, /* AVX-512 registers 24-31 */
118, 119, 120, 121, 122, 123, 124, 125, /* Mask registers */
+ 126, 127, 128, 129, /* bound registers */
};
/* Define the register numbers to be used in Dwarf debugging information.
@@ -2043,6 +2047,7 @@ int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER] =
-1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 16-23*/
-1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 24-31*/
93, 94, 95, 96, 97, 98, 99, 100, /* Mask registers */
+ -1, -1, -1, -1, /* bound registers */
};
/* Define parameter passing and return registers. */
@@ -2469,6 +2474,7 @@ ix86_target_string (HOST_WIDE_INT isa, int flags, const char *arch,
{ "-mrtm", OPTION_MASK_ISA_RTM },
{ "-mxsave", OPTION_MASK_ISA_XSAVE },
{ "-mxsaveopt", OPTION_MASK_ISA_XSAVEOPT },
+ { "-mmpx", OPTION_MASK_ISA_MPX },
};
/* Flag options. */
@@ -2963,6 +2969,7 @@ ix86_option_override_internal (bool main_args_p,
#define PTA_AVX512ER (HOST_WIDE_INT_1 << 41)
#define PTA_AVX512PF (HOST_WIDE_INT_1 << 42)
#define PTA_AVX512CD (HOST_WIDE_INT_1 << 43)
+#define PTA_MPX (HOST_WIDE_INT_1 << 44)
/* if this reaches 64, need to widen struct pta flags below */
@@ -4148,6 +4155,11 @@ ix86_conditional_register_usage (void)
for (i = FIRST_MASK_REG; i <= LAST_MASK_REG; i++)
fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = "";
}
+
+ /* If MPX is disabled, squash the registers. */
+ if (! TARGET_MPX)
+ for (i = FIRST_BND_REG; i <= LAST_BND_REG; i++)
+ fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = "";
}
@@ -8870,7 +8882,7 @@ ix86_code_end (void)
xops[0] = gen_rtx_REG (Pmode, regno);
xops[1] = gen_rtx_MEM (Pmode, stack_pointer_rtx);
output_asm_insn ("mov%z0\t{%1, %0|%0, %1}", xops);
- fputs ("\tret\n", asm_out_file);
+ output_asm_insn ("%!ret", NULL);
final_end_function ();
init_insn_lengths ();
free_after_compilation (cfun);
@@ -8928,7 +8940,7 @@ output_set_got (rtx dest, rtx label)
xops[2] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name));
xops[2] = gen_rtx_MEM (QImode, xops[2]);
- output_asm_insn ("call\t%X2", xops);
+ output_asm_insn ("%!call\t%X2", xops);
#if TARGET_MACHO
/* Output the Mach-O "canonical" pic base label name ("Lxx$pb") here.
@@ -14281,7 +14293,7 @@ print_reg (rtx x, int code, FILE *file)
case 8:
case 4:
case 12:
- if (! ANY_FP_REG_P (x))
+ if (! ANY_FP_REG_P (x) && ! ANY_BND_REG_P (x))
putc (code == 8 && TARGET_64BIT ? 'r' : 'e', file);
/* FALLTHRU */
case 16:
@@ -14404,6 +14416,7 @@ get_some_local_dynamic_name (void)
~ -- print "i" if TARGET_AVX2, "f" otherwise.
@ -- print a segment register of thread base pointer load
^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode
+ ! -- print MPX prefix for jxx/call/ret instructions if required.
*/
void
@@ -14898,6 +14911,11 @@ ix86_print_operand (FILE *file, rtx x, int code)
fputs ("addr32 ", file);
return;
+ case '!':
+ if (ix86_bnd_prefixed_insn_p (NULL_RTX))
+ fputs ("bnd ", file);
+ return;
+
default:
output_operand_lossage ("invalid operand code '%c'", code);
}
@@ -15040,7 +15058,7 @@ static bool
ix86_print_operand_punct_valid_p (unsigned char code)
{
return (code == '@' || code == '*' || code == '+' || code == '&'
- || code == ';' || code == '~' || code == '^');
+ || code == ';' || code == '~' || code == '^' || code == '!');
}
/* Print a memory operand whose address is ADDR. */
@@ -15070,6 +15088,25 @@ ix86_print_operand_address (FILE *file, rtx addr)
ok = ix86_decompose_address (XVECEXP (addr, 0, 0), &parts);
code = 'q';
}
+ else if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_BNDMK_ADDR)
+ {
+ ok = ix86_decompose_address (XVECEXP (addr, 0, 1), &parts);
+ gcc_assert (parts.base == NULL_RTX || parts.index == NULL_RTX);
+ if (parts.base != NULL_RTX)
+ {
+ parts.index = parts.base;
+ parts.scale = 1;
+ }
+ parts.base = XVECEXP (addr, 0, 0);
+ addr = XVECEXP (addr, 0, 0);
+ }
+ else if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_BNDLDX_ADDR)
+ {
+ ok = ix86_decompose_address (XVECEXP (addr, 0, 0), &parts);
+ gcc_assert (parts.index == NULL_RTX);
+ parts.index = XVECEXP (addr, 0, 1);
+ addr = XVECEXP (addr, 0, 0);
+ }
else
ok = ix86_decompose_address (addr, &parts);
@@ -24284,13 +24321,13 @@ ix86_output_call_insn (rtx insn, rtx call_op)
if (SIBLING_CALL_P (insn))
{
if (direct_p)
- xasm = "jmp\t%P0";
+ xasm = "%!jmp\t%P0";
/* SEH epilogue detection requires the indirect branch case
to include REX.W. */
else if (TARGET_SEH)
- xasm = "rex.W jmp %A0";
+ xasm = "%!rex.W jmp %A0";
else
- xasm = "jmp\t%A0";
+ xasm = "%!jmp\t%A0";
output_asm_insn (xasm, &call_op);
return "";
@@ -24327,9 +24364,9 @@ ix86_output_call_insn (rtx insn, rtx call_op)
}
if (direct_p)
- xasm = "call\t%P0";
+ xasm = "%!call\t%P0";
else
- xasm = "call\t%A0";
+ xasm = "%!call\t%A0";
output_asm_insn (xasm, &call_op);
@@ -34320,6 +34357,7 @@ ix86_class_likely_spilled_p (reg_class_t rclass)
case SSE_FIRST_REG:
case FP_TOP_REG:
case FP_SECOND_REG:
+ case BND_REGS:
return true;
default:
@@ -34668,6 +34706,8 @@ ix86_hard_regno_mode_ok (int regno, enum machine_mode mode)
return VALID_FP_MODE_P (mode);
if (MASK_REGNO_P (regno))
return VALID_MASK_REG_MODE (mode);
+ if (BND_REGNO_P (regno))
+ return VALID_BND_REG_MODE (mode);
if (SSE_REGNO_P (regno))
{
/* We implement the move patterns for all vector modes into and
@@ -35481,6 +35521,10 @@ x86_order_regs_for_local_alloc (void)
for (i = FIRST_MASK_REG; i <= LAST_MASK_REG; i++)
reg_alloc_order [pos++] = i;
+ /* MPX bound registers. */
+ for (i = FIRST_BND_REG; i <= LAST_BND_REG; i++)
+ reg_alloc_order [pos++] = i;
+
/* x87 registers. */
if (TARGET_SSE_MATH)
for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
@@ -41914,6 +41958,18 @@ ix86_expand_sse2_mulvxdi3 (rtx op0, rtx op1, rtx op2)
gen_rtx_MULT (mode, op1, op2));
}
+/* Return 1 if control tansfer instruction INSN
+ should be encoded with bnd prefix.
+ If insn is NULL then return 1 when control
+ transfer instructions should be prefixed with
+ bnd by default for current function. */
+
+bool
+ix86_bnd_prefixed_insn_p (rtx insn ATTRIBUTE_UNUSED)
+{
+ return false;
+}
+
/* Expand an insert into a vector register through pinsr insn.
Return true if successful. */
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 5267042..92299a2 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -945,7 +945,7 @@ enum target_cpu_default
eliminated during reloading in favor of either the stack or frame
pointer. */
-#define FIRST_PSEUDO_REGISTER 77
+#define FIRST_PSEUDO_REGISTER 81
/* Number of hardware registers that go into the DWARF-2 unwind info.
If not defined, equals FIRST_PSEUDO_REGISTER. */
@@ -977,7 +977,9 @@ enum target_cpu_default
/*xmm24,xmm25,xmm26,xmm27,xmm28,xmm29,xmm30,xmm31*/ \
0, 0, 0, 0, 0, 0, 0, 0, \
/* k0, k1, k2, k3, k4, k5, k6, k7*/ \
- 0, 0, 0, 0, 0, 0, 0, 0 }
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+/* b0, b1, b2, b3*/ \
+ 0, 0, 0, 0 }
/* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
@@ -1011,7 +1013,9 @@ enum target_cpu_default
/*xmm24,xmm25,xmm26,xmm27,xmm28,xmm29,xmm30,xmm31*/ \
6, 6, 6, 6, 6, 6, 6, 6, \
/* k0, k1, k2, k3, k4, k5, k6, k7*/ \
- 1, 1, 1, 1, 1, 1, 1, 1 }
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+/* b0, b1, b2, b3*/ \
+ 1, 1, 1, 1 }
/* Order in which to allocate registers. Each register must be
listed once, even those in FIXED_REGISTERS. List frame pointer
@@ -1027,7 +1031,8 @@ enum target_cpu_default
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, \
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, \
- 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76 }
+ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, \
+ 78, 79, 80 }
/* ADJUST_REG_ALLOC_ORDER is a macro which permits reg_alloc_order
to be rearranged based on a particular function. When using sse math,
@@ -1049,6 +1054,7 @@ enum target_cpu_default
#define HARD_REGNO_NREGS(REGNO, MODE) \
(STACK_REGNO_P (REGNO) || SSE_REGNO_P (REGNO) || MMX_REGNO_P (REGNO) \
+ || BND_REGNO_P (REGNO) \
? (COMPLEX_MODE_P (MODE) ? 2 : 1) \
: ((MODE) == XFmode \
? (TARGET_64BIT ? 2 : 3) \
@@ -1098,6 +1104,9 @@ enum target_cpu_default
|| (MODE) == V2SImode || (MODE) == SImode \
|| (MODE) == V4HImode || (MODE) == V8QImode)
+#define VALID_BND_REG_MODE(MODE) \
+ (TARGET_64BIT ? (MODE) == BND64mode : (MODE) == BND32mode)
+
#define VALID_DFP_MODE_P(MODE) \
((MODE) == SDmode || (MODE) == DDmode || (MODE) == TDmode)
@@ -1204,6 +1213,9 @@ enum target_cpu_default
#define FIRST_MASK_REG (LAST_EXT_REX_SSE_REG + 1) /*69*/
#define LAST_MASK_REG (FIRST_MASK_REG + 7) /*76*/
+#define FIRST_BND_REG (LAST_MASK_REG + 1) /*77*/
+#define LAST_BND_REG (FIRST_BND_REG + 3) /*80*/
+
/* Override this in other tm.h files to cope with various OS lossage
requiring a frame pointer. */
#ifndef SUBTARGET_FRAME_POINTER_REQUIRED
@@ -1284,6 +1296,7 @@ enum reg_class
SSE_FIRST_REG,
SSE_REGS,
EVEX_SSE_REGS,
+ BND_REGS,
ALL_SSE_REGS,
MMX_REGS,
FP_TOP_SSE_REGS,
@@ -1341,6 +1354,7 @@ enum reg_class
"SSE_FIRST_REG", \
"SSE_REGS", \
"EVEX_SSE_REGS", \
+ "BND_REGS", \
"ALL_SSE_REGS", \
"MMX_REGS", \
"FP_TOP_SSE_REGS", \
@@ -1360,37 +1374,38 @@ enum reg_class
TARGET_CONDITIONAL_REGISTER_USAGE. */
#define REG_CLASS_CONTENTS \
-{ { 0x00, 0x0, 0x0 }, \
- { 0x01, 0x0, 0x0 }, /* AREG */ \
- { 0x02, 0x0, 0x0 }, /* DREG */ \
- { 0x04, 0x0, 0x0 }, /* CREG */ \
- { 0x08, 0x0, 0x0 }, /* BREG */ \
- { 0x10, 0x0, 0x0 }, /* SIREG */ \
- { 0x20, 0x0, 0x0 }, /* DIREG */ \
- { 0x03, 0x0, 0x0 }, /* AD_REGS */ \
- { 0x0f, 0x0, 0x0 }, /* Q_REGS */ \
- { 0x1100f0, 0x1fe0, 0x0 }, /* NON_Q_REGS */ \
- { 0x7f, 0x1fe0, 0x0 }, /* INDEX_REGS */ \
- { 0x1100ff, 0x0, 0x0 }, /* LEGACY_REGS */ \
- { 0x07, 0x0, 0x0 }, /* CLOBBERED_REGS */ \
- { 0x1100ff, 0x1fe0, 0x0 }, /* GENERAL_REGS */ \
- { 0x100, 0x0, 0x0 }, /* FP_TOP_REG */ \
- { 0x0200, 0x0, 0x0 }, /* FP_SECOND_REG */ \
- { 0xff00, 0x0, 0x0 }, /* FLOAT_REGS */ \
- { 0x200000, 0x0, 0x0 }, /* SSE_FIRST_REG */ \
-{ 0x1fe00000, 0x1fe000, 0x0 }, /* SSE_REGS */ \
- { 0x0,0xffe00000, 0x1f }, /* EVEX_SSE_REGS */ \
-{ 0x1fe00000,0xffffe000, 0x1f }, /* ALL_SSE_REGS */ \
-{ 0xe0000000, 0x1f, 0x0 }, /* MMX_REGS */ \
-{ 0x1fe00100,0xffffe000, 0x1f }, /* FP_TOP_SSE_REG */ \
-{ 0x1fe00200,0xffffe000, 0x1f }, /* FP_SECOND_SSE_REG */ \
-{ 0x1fe0ff00,0xffffe000, 0x1f }, /* FLOAT_SSE_REGS */ \
-{ 0x11ffff, 0x1fe0, 0x0 }, /* FLOAT_INT_REGS */ \
-{ 0x1ff100ff,0xffffffe0, 0x1f }, /* INT_SSE_REGS */ \
-{ 0x1ff1ffff,0xffffffe0, 0x1f }, /* FLOAT_INT_SSE_REGS */ \
- { 0x0, 0x0,0x1fc0 }, /* MASK_EVEX_REGS */ \
- { 0x0, 0x0,0x1fe0 }, /* MASK_REGS */ \
-{ 0xffffffff,0xffffffff,0x1fff } \
+{ { 0x00, 0x0, 0x0 }, \
+ { 0x01, 0x0, 0x0 }, /* AREG */ \
+ { 0x02, 0x0, 0x0 }, /* DREG */ \
+ { 0x04, 0x0, 0x0 }, /* CREG */ \
+ { 0x08, 0x0, 0x0 }, /* BREG */ \
+ { 0x10, 0x0, 0x0 }, /* SIREG */ \
+ { 0x20, 0x0, 0x0 }, /* DIREG */ \
+ { 0x03, 0x0, 0x0 }, /* AD_REGS */ \
+ { 0x0f, 0x0, 0x0 }, /* Q_REGS */ \
+ { 0x1100f0, 0x1fe0, 0x0 }, /* NON_Q_REGS */ \
+ { 0x7f, 0x1fe0, 0x0 }, /* INDEX_REGS */ \
+ { 0x1100ff, 0x0, 0x0 }, /* LEGACY_REGS */ \
+ { 0x07, 0x0, 0x0 }, /* CLOBBERED_REGS */ \
+ { 0x1100ff, 0x1fe0, 0x0 }, /* GENERAL_REGS */ \
+ { 0x100, 0x0, 0x0 }, /* FP_TOP_REG */ \
+ { 0x0200, 0x0, 0x0 }, /* FP_SECOND_REG */ \
+ { 0xff00, 0x0, 0x0 }, /* FLOAT_REGS */ \
+ { 0x200000, 0x0, 0x0 }, /* SSE_FIRST_REG */ \
+{ 0x1fe00000, 0x1fe000, 0x0 }, /* SSE_REGS */ \
+ { 0x0,0xffe00000, 0x1f }, /* EVEX_SSE_REGS */ \
+ { 0x0, 0x0,0x1e000 }, /* BND_REGS */ \
+{ 0x1fe00000,0xffffe000, 0x1f }, /* ALL_SSE_REGS */ \
+{ 0xe0000000, 0x1f, 0x0 }, /* MMX_REGS */ \
+{ 0x1fe00100,0xffffe000, 0x1f }, /* FP_TOP_SSE_REG */ \
+{ 0x1fe00200,0xffffe000, 0x1f }, /* FP_SECOND_SSE_REG */ \
+{ 0x1fe0ff00,0xffffe000, 0x1f }, /* FLOAT_SSE_REGS */ \
+{ 0x11ffff, 0x1fe0, 0x0 }, /* FLOAT_INT_REGS */ \
+{ 0x1ff100ff,0xffffffe0, 0x1f }, /* INT_SSE_REGS */ \
+{ 0x1ff1ffff,0xffffffe0, 0x1f }, /* FLOAT_INT_SSE_REGS */ \
+ { 0x0, 0x0, 0x1fc0 }, /* MASK_EVEX_REGS */ \
+ { 0x0, 0x0, 0x1fe0 }, /* MASK_REGS */ \
+{ 0xffffffff,0xffffffff, 0x1fff } \
}
/* The same information, inverted:
@@ -1466,6 +1481,9 @@ enum reg_class
#define CC_REG_P(X) (REG_P (X) && CC_REGNO_P (REGNO (X)))
#define CC_REGNO_P(X) ((X) == FLAGS_REG || (X) == FPSR_REG)
+#define BND_REGNO_P(N) IN_RANGE ((N), FIRST_BND_REG, LAST_BND_REG)
+#define ANY_BND_REG_P(X) (REG_P (X) && BND_REGNO_P (REGNO (X)))
+
/* The class value for index registers, and the one for base regs. */
#define INDEX_REG_CLASS INDEX_REGS
@@ -1910,6 +1928,9 @@ do { \
between pointers and any other objects of this machine mode. */
#define Pmode (ix86_pmode == PMODE_DI ? DImode : SImode)
+/* Specify the machine mode that bounds have. */
+#define BNDmode (ix86_pmode == PMODE_DI ? BND64mode : BND32mode)
+
/* A C expression whose value is zero if pointers that need to be extended
from being `POINTER_SIZE' bits wide to `Pmode' are sign-extended and
greater then zero if they are zero-extended and less then zero if the
@@ -2020,7 +2041,8 @@ do { \
"xmm20", "xmm21", "xmm22", "xmm23", \
"xmm24", "xmm25", "xmm26", "xmm27", \
"xmm28", "xmm29", "xmm30", "xmm31", \
- "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7" }
+ "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7", \
+ "bnd0", "bnd1", "bnd2", "bnd3" }
#define REGISTER_NAMES HI_REGISTER_NAMES
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index d06de40..bb2581b 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -63,6 +63,7 @@
;; ~ -- print "i" if TARGET_AVX2, "f" otherwise.
;; @ -- print a segment register of thread base pointer load
;; ^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode
+;; ! -- print MPX prefix for jxx/call/ret instructions if required.
(define_c_enum "unspec" [
;; Relocation specifiers
@@ -178,6 +179,16 @@
;; For BMI2 support
UNSPEC_PDEP
UNSPEC_PEXT
+
+ UNSPEC_BNDMK
+ UNSPEC_BNDMK_ADDR
+ UNSPEC_BNDSTX
+ UNSPEC_BNDLDX
+ UNSPEC_BNDLDX_ADDR
+ UNSPEC_BNDCL
+ UNSPEC_BNDCU
+ UNSPEC_BNDCN
+ UNSPEC_MPX_FENCE
])
(define_c_enum "unspecv" [
@@ -336,6 +347,8 @@
(MASK5_REG 74)
(MASK6_REG 75)
(MASK7_REG 76)
+ (BND0_REG 77)
+ (BND1_REG 78)
])
;; Insns whose names begin with "x86_" are emitted by gen_FOO calls
@@ -369,7 +382,8 @@
ssecvt,ssecvt1,sseicvt,sseins,
sseshuf,sseshuf1,ssemuladd,sse4arg,
lwp,mskmov,msklog,
- mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft"
+ mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft,
+ mpxmov,mpxmk,mpxchk,mpxld,mpxst"
(const_string "other"))
;; Main data type used by the insn
@@ -398,7 +412,8 @@
;; The (bounding maximum) length of an instruction immediate.
(define_attr "length_immediate" ""
(cond [(eq_attr "type" "incdec,setcc,icmov,str,lea,other,multi,idiv,leave,
- bitmanip,imulx,msklog,mskmov")
+ bitmanip,imulx,msklog,mskmov,mpxmk,mpxmov,mpxchk,
+ mpxld,mpxst")
(const_int 0)
(eq_attr "unit" "i387,sse,mmx")
(const_int 0)
@@ -453,13 +468,17 @@
(const_int 0)
(and (eq_attr "unit" "sse") (eq_attr "mode" "SF,DF"))
(const_int 1)
+ (and (eq_attr "type" "ibr,call,callv")
+ (match_test "ix86_bnd_prefixed_insn_p (insn)"))
+ (const_int 1)
]
(const_int 0)))
;; Set when 0f opcode prefix is used.
(define_attr "prefix_0f" ""
(if_then_else
- (ior (eq_attr "type" "imovx,setcc,icmov,bitmanip,msklog,mskmov")
+ (ior (eq_attr "type" "imovx,setcc,icmov,bitmanip,msklog,mskmov,
+ mpxmk,mpxmov,mpxchk,mpxld,mpxst")
(eq_attr "unit" "sse,mmx"))
(const_int 1)
(const_int 0)))
@@ -562,12 +581,19 @@
]
(const_int 1)))
+;; When this attribute is set, calculate total insn length from
+;; length_nobnd attribute, prefixed with eventual bnd prefix byte
+(define_attr "length_nobnd" "" (const_int 0))
+
;; The (bounding maximum) length of an instruction in bytes.
;; ??? fistp and frndint are in fact fldcw/{fistp,frndint}/fldcw sequences.
;; Later we may want to split them and compute proper length as for
;; other insns.
(define_attr "length" ""
- (cond [(eq_attr "type" "other,multi,fistp,frndint")
+ (cond [(eq_attr "length_nobnd" "!0")
+ (plus (symbol_ref ("ix86_bnd_prefixed_insn_p (insn)"))
+ (attr "length_nobnd"))
+ (eq_attr "type" "other,multi,fistp,frndint")
(const_int 16)
(eq_attr "type" "fcmp")
(const_int 4)
@@ -608,12 +634,16 @@
(define_attr "memory" "none,load,store,both,unknown"
(cond [(eq_attr "type" "other,multi,str,lwp")
(const_string "unknown")
- (eq_attr "type" "lea,fcmov,fpspc")
+ (eq_attr "type" "lea,fcmov,fpspc,mpxmk,mpxchk")
(const_string "none")
(eq_attr "type" "fistp,leave")
(const_string "both")
(eq_attr "type" "frndint")
(const_string "load")
+ (eq_attr "type" "mpxld")
+ (const_string "load")
+ (eq_attr "type" "mpxst")
+ (const_string "store")
(eq_attr "type" "push")
(if_then_else (match_operand 1 "memory_operand")
(const_string "both")
@@ -659,7 +689,7 @@
fmov,fcmp,fsgn,
sse,ssemov,ssecmp,ssecomi,ssecvt,ssecvt1,sseicvt,
sselog1,sseshuf1,sseadd1,sseiadd1,sseishft1,
- mmx,mmxmov,mmxcmp,mmxcvt,mskmov,msklog")
+ mmx,mmxmov,mmxcmp,mmxcvt,mskmov,msklog,mpxmov")
(match_operand 2 "memory_operand"))
(const_string "load")
(and (eq_attr "type" "icmov,ssemuladd,sse4arg")
@@ -893,6 +923,21 @@
(define_mode_iterator DWIH [(SI "!TARGET_64BIT")
(DI "TARGET_64BIT")])
+;; Bound modes.
+(define_mode_iterator BND [(BND32 "!TARGET_LP64")
+ (BND64 "TARGET_LP64")])
+
+;; Pointer mode corresponding to bound mode.
+(define_mode_attr bnd_ptr [(BND32 "SI") (BND64 "DI")])
+
+;; MPX check types
+(define_int_iterator BNDCHECK [UNSPEC_BNDCL UNSPEC_BNDCU UNSPEC_BNDCN])
+
+;; Check name
+(define_int_attr bndcheck [(UNSPEC_BNDCL "cl")
+ (UNSPEC_BNDCU "cu")
+ (UNSPEC_BNDCN "cn")])
+
;; Instruction suffix for integer modes.
(define_mode_attr imodesuffix [(QI "b") (HI "w") (SI "l") (DI "q")])
@@ -5347,7 +5392,7 @@
(define_insn_and_split "*lea<mode>"
[(set (match_operand:SWI48 0 "register_operand" "=r")
- (match_operand:SWI48 1 "lea_address_operand" "p"))]
+ (match_operand:SWI48 1 "address_no_seg_operand" "p"))]
""
{
if (SImode_address_operand (operands[1], VOIDmode))
@@ -10734,10 +10779,10 @@
(label_ref (match_operand 0))
(pc)))]
""
- "%+j%C1\t%l0"
+ "%!%+j%C1\t%l0"
[(set_attr "type" "ibr")
(set_attr "modrm" "0")
- (set (attr "length")
+ (set (attr "length_nobnd")
(if_then_else (and (ge (minus (match_dup 0) (pc))
(const_int -126))
(lt (minus (match_dup 0) (pc))
@@ -10752,10 +10797,10 @@
(pc)
(label_ref (match_operand 0))))]
""
- "%+j%c1\t%l0"
+ "%!%+j%c1\t%l0"
[(set_attr "type" "ibr")
(set_attr "modrm" "0")
- (set (attr "length")
+ (set (attr "length_nobnd")
(if_then_else (and (ge (minus (match_dup 0) (pc))
(const_int -126))
(lt (minus (match_dup 0) (pc))
@@ -11218,9 +11263,9 @@
[(set (pc)
(label_ref (match_operand 0)))]
""
- "jmp\t%l0"
+ "%!jmp\t%l0"
[(set_attr "type" "ibr")
- (set (attr "length")
+ (set (attr "length_nobnd")
(if_then_else (and (ge (minus (match_dup 0) (pc))
(const_int -126))
(lt (minus (match_dup 0) (pc))
@@ -11240,7 +11285,7 @@
(define_insn "*indirect_jump"
[(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw"))]
""
- "jmp\t%A0"
+ "%!jmp\t%A0"
[(set_attr "type" "ibr")
(set_attr "length_immediate" "0")])
@@ -11289,7 +11334,7 @@
[(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw"))
(use (label_ref (match_operand 1)))]
""
- "jmp\t%A0"
+ "%!jmp\t%A0"
[(set_attr "type" "ibr")
(set_attr "length_immediate" "0")])
@@ -11676,8 +11721,8 @@
(define_insn "simple_return_internal"
[(simple_return)]
"reload_completed"
- "ret"
- [(set_attr "length" "1")
+ "%!ret"
+ [(set_attr "length_nobnd" "1")
(set_attr "atom_unit" "jeu")
(set_attr "length_immediate" "0")
(set_attr "modrm" "0")])
@@ -11689,7 +11734,12 @@
[(simple_return)
(unspec [(const_int 0)] UNSPEC_REP)]
"reload_completed"
- "rep%; ret"
+{
+ if (ix86_bnd_prefixed_insn_p (insn))
+ return "%!ret";
+
+ return "rep%; ret";
+}
[(set_attr "length" "2")
(set_attr "atom_unit" "jeu")
(set_attr "length_immediate" "0")
@@ -11700,8 +11750,8 @@
[(simple_return)
(use (match_operand:SI 0 "const_int_operand"))]
"reload_completed"
- "ret\t%0"
- [(set_attr "length" "3")
+ "%!ret\t%0"
+ [(set_attr "length_nobnd" "3")
(set_attr "atom_unit" "jeu")
(set_attr "length_immediate" "2")
(set_attr "modrm" "0")])
@@ -11710,7 +11760,7 @@
[(simple_return)
(use (match_operand:SI 0 "register_operand" "r"))]
"reload_completed"
- "jmp\t%A0"
+ "%!jmp\t%A0"
[(set_attr "type" "ibr")
(set_attr "length_immediate" "0")])
@@ -18173,6 +18223,131 @@
[(set_attr "type" "other")
(set_attr "length" "3")])
+;; MPX instructions
+
+(define_expand "<mode>_mk"
+ [(set (match_operand:BND 0 "register_operand")
+ (unspec:BND
+ [(mem:<bnd_ptr>
+ (match_par_dup 3
+ [(match_operand:<bnd_ptr> 1 "register_operand")
+ (match_operand:<bnd_ptr> 2 "address_mpx_no_base_operand")]))]
+ UNSPEC_BNDMK))]
+ "TARGET_MPX"
+{
+ operands[3] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1],
+ operands[2]),
+ UNSPEC_BNDMK_ADDR);
+})
+
+(define_insn "*<mode>_mk"
+ [(set (match_operand:BND 0 "register_operand" "=B")
+ (unspec:BND
+ [(match_operator:<bnd_ptr> 3 "bnd_mem_operator"
+ [(unspec:<bnd_ptr>
+ [(match_operand:<bnd_ptr> 1 "register_operand" "r")
+ (match_operand:<bnd_ptr> 2 "address_mpx_no_base_operand" "Tb")]
+ UNSPEC_BNDMK_ADDR)])]
+ UNSPEC_BNDMK))]
+ "TARGET_MPX"
+ "bndmk\t{%3, %0|%0, %3}"
+ [(set_attr "type" "mpxmk")])
+
+(define_expand "mov<mode>"
+ [(set (match_operand:BND 0 "general_operand")
+ (match_operand:BND 1 "general_operand"))]
+ "TARGET_MPX"
+{
+ ix86_expand_move (<MODE>mode, operands);DONE;
+})
+
+(define_insn "*mov<mode>_internal_mpx"
+ [(set (match_operand:BND 0 "nonimmediate_operand" "=B,m")
+ (match_operand:BND 1 "general_operand" "Bm,B"))]
+ "TARGET_MPX"
+ "bndmov\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mpxmov")])
+
+(define_expand "<mode>_<bndcheck>"
+ [(parallel [(unspec [(match_operand:BND 0 "register_operand")
+ (match_operand:<bnd_ptr> 1 "address_no_seg_operand")] BNDCHECK)
+ (set (match_dup 2)
+ (unspec:BLK [(match_dup 2)] UNSPEC_MPX_FENCE))])]
+ "TARGET_MPX"
+{
+ operands[2] = gen_rtx_MEM (BLKmode, operands[1]);
+ MEM_VOLATILE_P (operands[2]) = 1;
+})
+
+(define_insn "*<mode>_<bndcheck>"
+ [(parallel [(unspec [(match_operand:BND 0 "register_operand" "B")
+ (match_operand:<bnd_ptr> 1 "address_no_seg_operand" "p")] BNDCHECK)
+ (set (match_operand:BLK 2 "bnd_mem_operator")
+ (unspec:BLK [(match_dup 2)] UNSPEC_MPX_FENCE))])]
+ "TARGET_MPX"
+ "bnd<bndcheck>\t{%a1, %0|%0, %a1}"
+ [(set_attr "type" "mpxchk")])
+
+(define_expand "<mode>_ldx"
+ [(parallel [(set:BND (match_operand:BND 0 "register_operand")
+ (unspec:BND
+ [(mem:<bnd_ptr>
+ (match_par_dup 3
+ [(match_operand:<bnd_ptr> 1 "address_mpx_no_index_operand")
+ (match_operand:<bnd_ptr> 2 "register_operand")]))]
+ UNSPEC_BNDLDX))
+ (use (mem:BLK (match_dup 1)))])]
+ "TARGET_MPX"
+{
+ operands[3] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1],
+ operands[2]),
+ UNSPEC_BNDLDX_ADDR);
+})
+
+(define_insn "*<mode>_ldx"
+ [(parallel [(set:BND (match_operand:BND 0 "register_operand" "=B")
+ (unspec:BND
+ [(match_operator:<bnd_ptr> 3 "bnd_mem_operator"
+ [(unspec:<bnd_ptr>
+ [(match_operand:<bnd_ptr> 1 "address_mpx_no_index_operand" "Ti")
+ (match_operand:<bnd_ptr> 2 "register_operand" "l")]
+ UNSPEC_BNDLDX_ADDR)])]
+ UNSPEC_BNDLDX))
+ (use (mem:BLK (match_dup 1)))])]
+ "TARGET_MPX"
+ "bndldx\t{%3, %0|%0, %3}"
+ [(set_attr "type" "mpxld")])
+
+(define_expand "<mode>_stx"
+ [(parallel [(unspec [(mem:<bnd_ptr>
+ (match_par_dup 3
+ [(match_operand:<bnd_ptr> 0 "address_mpx_no_index_operand")
+ (match_operand:<bnd_ptr> 1 "register_operand")]))
+ (match_operand:BND 2 "register_operand")] UNSPEC_BNDSTX)
+ (set (match_dup 4)
+ (unspec:BLK [(match_dup 4)] UNSPEC_MPX_FENCE))])]
+ "TARGET_MPX"
+{
+ operands[3] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[0],
+ operands[1]),
+ UNSPEC_BNDLDX_ADDR);
+ operands[4] = gen_rtx_MEM (BLKmode, operands[0]);
+ MEM_VOLATILE_P (operands[4]) = 1;
+})
+
+(define_insn "*<mode>_stx"
+ [(parallel [(unspec [(match_operator:<bnd_ptr> 3 "bnd_mem_operator"
+ [(unspec:<bnd_ptr>
+ [(match_operand:<bnd_ptr> 0 "address_mpx_no_index_operand" "Ti")
+ (match_operand:<bnd_ptr> 1 "register_operand" "l")]
+ UNSPEC_BNDLDX_ADDR)])
+ (match_operand:BND 2 "register_operand" "B")] UNSPEC_BNDSTX)
+ (set (match_operand:BLK 4 "bnd_mem_operator")
+ (unspec:BLK [(match_dup 4)] UNSPEC_MPX_FENCE))])]
+ "TARGET_MPX"
+ "bndstx\t{%2, %3|%3, %2}"
+ [(set_attr "type" "mpxst")])
+
(include "mmx.md")
(include "sse.md")
(include "sync.md")
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 1e624ab..1a1b8ab 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -669,6 +669,10 @@ mrtm
Target Report Mask(ISA_RTM) Var(ix86_isa_flags) Save
Support RTM built-in functions and code generation
+mmpx
+Target Report Mask(ISA_MPX) Var(ix86_isa_flags) Save
+Support MPX code generation
+
mstack-protector-guard=
Target RejectNegative Joined Enum(stack_protector_guard) Var(ix86_stack_protector_guard) Init(SSP_TLS)
Use given stack-protector guard
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 06b2914..d1a4f66 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -875,7 +875,7 @@
;; Return true if op if a valid address for LEA, and does not contain
;; a segment override. Defined as a special predicate to allow
;; mode-less const_int operands pass to address_operand.
-(define_special_predicate "lea_address_operand"
+(define_special_predicate "address_no_seg_operand"
(match_operand 0 "address_operand")
{
struct ix86_address parts;
@@ -932,9 +932,74 @@
return true;
})
+;; Return true if op is valid MPX address operand without base
+(define_predicate "address_mpx_no_base_operand"
+ (match_operand 0 "address_operand")
+{
+ struct ix86_address parts;
+ int ok;
+
+ ok = ix86_decompose_address (op, &parts);
+ gcc_assert (ok);
+
+ if (parts.index && parts.base)
+ return false;
+
+ if (parts.seg != SEG_DEFAULT)
+ return false;
+
+ /* Do not support (%rip). */
+ if (parts.disp && flag_pic && TARGET_64BIT
+ && SYMBOLIC_CONST (parts.disp))
+ {
+ if (GET_CODE (parts.disp) != CONST
+ || GET_CODE (XEXP (parts.disp, 0)) != PLUS
+ || GET_CODE (XEXP (XEXP (parts.disp, 0), 0)) != UNSPEC
+ || !CONST_INT_P (XEXP (XEXP (parts.disp, 0), 1))
+ || (XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_DTPOFF
+ && XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_NTPOFF))
+ return false;
+ }
+
+ return true;
+})
+
+;; Return true if op is valid MPX address operand without index
+(define_predicate "address_mpx_no_index_operand"
+ (match_operand 0 "address_operand")
+{
+ struct ix86_address parts;
+ int ok;
+
+ ok = ix86_decompose_address (op, &parts);
+ gcc_assert (ok);
+
+ if (parts.index)
+ return false;
+
+ if (parts.seg != SEG_DEFAULT)
+ return false;
+
+ /* Do not support (%rip). */
+ if (parts.disp && flag_pic && TARGET_64BIT
+ && SYMBOLIC_CONST (parts.disp)
+ && (GET_CODE (parts.disp) != CONST
+ || GET_CODE (XEXP (parts.disp, 0)) != PLUS
+ || GET_CODE (XEXP (XEXP (parts.disp, 0), 0)) != UNSPEC
+ || !CONST_INT_P (XEXP (XEXP (parts.disp, 0), 1))
+ || (XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_DTPOFF
+ && XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_NTPOFF)))
+ return false;
+
+ return true;
+})
+
(define_predicate "vsib_mem_operator"
(match_code "mem"))
+(define_predicate "bnd_mem_operator"
+ (match_code "mem"))
+
;; Return true if the rtx is known to be at least 32 bits aligned.
(define_predicate "aligned_operand"
(match_operand 0 "general_operand")