From patchwork Wed Apr 16 11:35:55 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilya Enkovich X-Patchwork-Id: 339557 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 2E724140096 for ; Wed, 16 Apr 2014 21:36:23 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=kvIdNvzbYuuEdc8b42SKInjoTd1Awch2Pr+lV8ef5O27hwKdWSpSo BNToeFBZMOyZqTu7JNYZUvm9DZiM+0HdOawfMH9Sn7WIBrZd6uLboz6ADSjFNxFO huKi1VLEjOiSzoUEDC5rfrJ3CRX+M+5wzptsDMi5sU2tlJxye4KPtc= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=g6iptogKKd5xLPdWwWHKpM4W/Uc=; b=RXRYae1Aql0HCW4um3s9 /RSJloG3N2+mV7OGnVBrvEh5zs4z3GxlHqEtCCKclvTQDdX7qfzS98Q0d+rH1v/+ vGVfKBbST9D1xugVrw5MbGvOLbG4NjPWtWCf77OwSv909uWhuynFMl8uaYgG8O5g +cDtDKVGTedqKAETlgiSBMA= Received: (qmail 3159 invoked by alias); 16 Apr 2014 11:36:14 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 3149 invoked by uid 89); 16 Apr 2014 11:36:14 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.5 required=5.0 tests=AWL, BAYES_50, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-pb0-f48.google.com Received: from mail-pb0-f48.google.com (HELO mail-pb0-f48.google.com) (209.85.160.48) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Wed, 16 Apr 2014 11:36:09 +0000 Received: by mail-pb0-f48.google.com with SMTP id md12so10736576pbc.21 for ; Wed, 16 Apr 2014 04:36:07 -0700 (PDT) X-Received: by 10.68.211.233 with SMTP id nf9mr7888332pbc.29.1397648167629; Wed, 16 Apr 2014 04:36:07 -0700 (PDT) Received: from msticlxl57.ims.intel.com (fmdmzpr04-ext.fm.intel.com. [192.55.55.39]) by mx.google.com with ESMTPSA id ir10sm46437753pbc.59.2014.04.16.04.36.04 for (version=TLSv1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 16 Apr 2014 04:36:06 -0700 (PDT) Date: Wed, 16 Apr 2014 15:35:55 +0400 From: Ilya Enkovich To: gcc-patches@gcc.gnu.org Subject: [PATCH, i386, Pointer Bounds Checker 2/x] Intel Memory Protection Extensions (MPX) instructions support Message-ID: <20140416113555.GA4040@msticlxl57.ims.intel.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes Hi, This patch introduces Intel MPX bound registers and instructions. It was approved earlier for 4.9 and had no significant changes since then. I'll assume patch is OK if no objections arise. Patch was bootstrapped and tested for linux-x86_64. Thanks, Ilya --- gcc/ 2014-04-16 Ilya Enkovich * mode-classes.def (MODE_BOUND): New. * tree.def (BOUND_TYPE): New. * genmodes.c (complete_mode): Support MODE_BOUND. (BOUND_MODE): New. (make_bound_mode): New. * machmode.h (BOUND_MODE_P): New. * stor-layout.c (int_mode_for_mode): Support MODE_BOUND. (layout_type): Support BOUND_TYPE. * tree-pretty-print.c (dump_generic_node): Support BOUND_TYPE. * tree.c (build_int_cst_wide): Support BOUND_TYPE. (type_contains_placeholder_1): Likewise. * tree.h (BOUND_TYPE_P): New. * varasm.c (output_constant): Support BOUND_TYPE. * config/i386/constraints.md (B): New. (Ti): New. (Tb): New. * 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_code_end): Add MPX bnd prefix. (output_set_got): Likewise. (ix86_output_call_insn): Likewise. (get_some_local_dynamic_name): 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. (BND): New. (bnd_ptr): New. (BNDCHECK): New. (bndcheck): New. (*jcc_1): Add MPX bnd prefix and fix length. (*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. (_mk): New. (*_mk): New. (mov): New. (*mov_internal_mpx): New. (_): New. (*_): New. (_ldx): New. (*_ldx): New. (_stx): New. (*_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. diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md index 567e705..3cd7e43 100644 --- a/gcc/config/i386/constraints.md +++ b/gcc/config/i386/constraints.md @@ -18,7 +18,7 @@ ;; . ;;; Unused letters: -;;; B H +;;; 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 @@ -243,6 +246,8 @@ ;; T prefix is used for different address constraints ;; v - VSIB address ;; s - address with no segment register +;; i - address with no index and no rip +;; b - address with no base and no rip (define_address_constraint "Tv" "VSIB address operand" @@ -251,3 +256,11 @@ (define_address_constraint "Ts" "Address operand without segment register" (match_operand 0 "address_no_seg_operand")) + +(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 c9977bf..87ec735 100644 --- a/gcc/config/i386/i386-c.c +++ b/gcc/config/i386/i386-c.c @@ -393,6 +393,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 07e5720..0e302e3 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 6e32978..7a909f9 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -240,6 +240,8 @@ extern void ix86_expand_sse2_mulv4si3 (rtx, rtx, rtx); extern void ix86_expand_sse2_mulvxdi3 (rtx, rtx, rtx); extern void ix86_expand_sse2_abs (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 3eefe4a..6a99b6b 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -2127,6 +2127,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. */ @@ -2143,6 +2145,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. */ @@ -2159,6 +2162,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. @@ -2227,6 +2231,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 */ + 101, 102, 103, 104, /* bound registers */ }; /* Define parameter passing and return registers. */ @@ -2623,6 +2628,7 @@ ix86_target_string (HOST_WIDE_INT isa, int flags, const char *arch, { "-mxsave", OPTION_MASK_ISA_XSAVE }, { "-mxsaveopt", OPTION_MASK_ISA_XSAVEOPT }, { "-mprefetchwt1", OPTION_MASK_ISA_PREFETCHWT1 }, + { "-mmpx", OPTION_MASK_ISA_MPX }, }; /* Flag options. */ @@ -3112,6 +3118,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) #define PTA_SHA (HOST_WIDE_INT_1 << 45) #define PTA_PREFETCHWT1 (HOST_WIDE_INT_1 << 46) @@ -3671,12 +3678,18 @@ ix86_option_override_internal (bool main_args_p, if (processor_alias_table[i].flags & PTA_PREFETCHWT1 && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_PREFETCHWT1)) opts->x_ix86_isa_flags |= OPTION_MASK_ISA_PREFETCHWT1; + if (processor_alias_table[i].flags & PTA_MPX + && !(opts->x_ix86_isa_flags_explicit & OPTION_MASK_ISA_MPX)) + opts->x_ix86_isa_flags |= OPTION_MASK_ISA_MPX; if (processor_alias_table[i].flags & (PTA_PREFETCH_SSE | PTA_SSE)) x86_prefetch_sse = true; break; } + if (TARGET_X32 && (opts->x_ix86_isa_flags & OPTION_MASK_ISA_MPX)) + error ("Intel MPX does not support x32"); + if (!strcmp (opts->x_ix86_arch_string, "generic")) error ("generic CPU can be used only for %stune=%s %s", prefix, suffix, sw); @@ -4332,6 +4345,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] = ""; } @@ -9205,7 +9223,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); @@ -9263,7 +9281,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. @@ -14654,7 +14672,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: @@ -14778,6 +14796,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 @@ -15320,6 +15339,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); } @@ -15462,7 +15486,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. */ @@ -15492,6 +15516,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); @@ -24931,13 +24974,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 ""; @@ -24974,9 +25017,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); @@ -37227,6 +37270,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: @@ -37575,6 +37619,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 @@ -38397,6 +38443,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++) @@ -45134,6 +45184,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; +} + /* Calculate integer abs() using only SSE2 instructions. */ void diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 51659de..e0ced33 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -132,6 +132,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define TARGET_XSAVEOPT_P(x) TARGET_ISA_XSAVEOPT_P(x) #define TARGET_PREFETCHWT1 TARGET_ISA_PREFETCHWT1 #define TARGET_PREFETCHWT1_P(x) TARGET_ISA_PREFETCHWT1_P(x) +#define TARGET_MPX TARGET_ISA_MPX +#define TARGET_MPX_P(x) TARGET_ISA_MPX_P(x) #define TARGET_LP64 TARGET_ABI_64 #define TARGET_LP64_P(x) TARGET_ABI_64_P(x) @@ -935,7 +937,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); 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. */ @@ -967,7 +969,9 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); /*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 @@ -1001,7 +1005,9 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); /*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 @@ -1017,7 +1023,8 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); 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, @@ -1039,6 +1046,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #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) \ @@ -1088,6 +1096,9 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); || (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) @@ -1194,6 +1205,9 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #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 @@ -1274,6 +1288,7 @@ enum reg_class SSE_FIRST_REG, SSE_REGS, EVEX_SSE_REGS, + BND_REGS, ALL_SSE_REGS, MMX_REGS, FP_TOP_SSE_REGS, @@ -1331,6 +1346,7 @@ enum reg_class "SSE_FIRST_REG", \ "SSE_REGS", \ "EVEX_SSE_REGS", \ + "BND_REGS", \ "ALL_SSE_REGS", \ "MMX_REGS", \ "FP_TOP_SSE_REGS", \ @@ -1350,37 +1366,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: @@ -1456,6 +1473,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 @@ -1902,6 +1922,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 @@ -2012,7 +2035,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 25e2e93..32db2c6 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 @@ -181,6 +182,16 @@ ;; For AVX512F support UNSPEC_KMOV + + 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" [ @@ -355,6 +366,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 @@ -389,7 +402,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 @@ -425,7 +439,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) @@ -480,13 +495,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))) @@ -589,12 +608,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) @@ -635,12 +661,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") @@ -686,7 +716,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") @@ -939,6 +969,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")]) @@ -10694,10 +10739,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)) @@ -10712,10 +10757,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)) @@ -11153,9 +11198,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)) @@ -11175,7 +11220,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")]) @@ -11224,7 +11269,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")]) @@ -11611,8 +11656,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")]) @@ -11624,7 +11669,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") @@ -11635,8 +11685,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")]) @@ -11645,7 +11695,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")]) @@ -18165,6 +18215,131 @@ [(set_attr "type" "other") (set_attr "length" "3")]) +;; MPX instructions + +(define_expand "_mk" + [(set (match_operand:BND 0 "register_operand") + (unspec:BND + [(mem: + (match_par_dup 3 + [(match_operand: 1 "register_operand") + (match_operand: 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 "*_mk" + [(set (match_operand:BND 0 "register_operand" "=B") + (unspec:BND + [(match_operator: 3 "bnd_mem_operator" + [(unspec: + [(match_operand: 1 "register_operand" "r") + (match_operand: 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" + [(set (match_operand:BND 0 "general_operand") + (match_operand:BND 1 "general_operand"))] + "TARGET_MPX" +{ + ix86_expand_move (mode, operands);DONE; +}) + +(define_insn "*mov_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 "_" + [(parallel [(unspec [(match_operand:BND 0 "register_operand") + (match_operand: 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 "*_" + [(parallel [(unspec [(match_operand:BND 0 "register_operand" "B") + (match_operand: 1 "address_no_seg_operand" "Ts")] BNDCHECK) + (set (match_operand:BLK 2 "bnd_mem_operator") + (unspec:BLK [(match_dup 2)] UNSPEC_MPX_FENCE))])] + "TARGET_MPX" + "bnd\t{%a1, %0|%0, %a1}" + [(set_attr "type" "mpxchk")]) + +(define_expand "_ldx" + [(parallel [(set:BND (match_operand:BND 0 "register_operand") + (unspec:BND + [(mem: + (match_par_dup 3 + [(match_operand: 1 "address_mpx_no_index_operand") + (match_operand: 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 "*_ldx" + [(parallel [(set:BND (match_operand:BND 0 "register_operand" "=B") + (unspec:BND + [(match_operator: 3 "bnd_mem_operator" + [(unspec: + [(match_operand: 1 "address_mpx_no_index_operand" "Ti") + (match_operand: 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 "_stx" + [(parallel [(unspec [(mem: + (match_par_dup 3 + [(match_operand: 0 "address_mpx_no_index_operand") + (match_operand: 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 "*_stx" + [(parallel [(unspec [(match_operator: 3 "bnd_mem_operator" + [(unspec: + [(match_operand: 0 "address_mpx_no_index_operand" "Ti") + (match_operand: 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 0f463a2..45b675a 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -781,6 +781,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 2ef1384..a738033 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -1020,9 +1020,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") diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 860a545..33ee338 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -669,7 +669,7 @@ Objective-C and Objective-C++ Dialects}. -mavx2 -mavx512f -mavx512pf -mavx512er -mavx512cd -msha @gol -maes -mpclmul -mfsgsbase -mrdrnd -mf16c -mfma -mprefetchwt1 @gol -msse4a -m3dnow -mpopcnt -mabm -mbmi -mtbm -mfma4 -mxop -mlzcnt @gol --mbmi2 -mfxsr -mxsave -mxsaveopt -mrtm -mlwp -mthreads @gol +-mbmi2 -mfxsr -mxsave -mxsaveopt -mrtm -mlwp -mmpx -mthreads @gol -mno-align-stringops -minline-all-stringops @gol -minline-stringops-dynamically -mstringop-strategy=@var{alg} @gol -mmemcpy-strategy=@var{strategy} -mmemset-strategy=@var{strategy} @@ -15308,6 +15308,8 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}. @itemx -mrtm @itemx -mtbm @itemx -mno-tbm +@itemx -mmpx +@itemx -mno-mpx @opindex mmmx @opindex mno-mmx @opindex msse @@ -15317,7 +15319,7 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}. These switches enable or disable the use of instructions in the MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, AVX, AVX2, AVX512F, AVX512PF, AVX512ER, AVX512CD, SHA, AES, PCLMUL, FSGSBASE, RDRND, F16C, FMA, SSE4A, FMA4, XOP, LWP, ABM, -BMI, BMI2, FXSR, XSAVE, XSAVEOPT, LZCNT, RTM, or 3DNow!@: +BMI, BMI2, FXSR, XSAVE, XSAVEOPT, LZCNT, RTM, MPX or 3DNow!@: extended instruction sets. These extensions are also available as built-in functions: see @ref{X86 Built-in Functions}, for details of the functions enabled and diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index 3a1014d..9daed1d 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -1295,6 +1295,12 @@ These modes stand for a complex number represented as a pair of integer values. The integer values are in @code{QImode}, @code{HImode}, @code{SImode}, @code{DImode}, @code{TImode}, and @code{OImode}, respectively. + +@findex BND32mode +@findex BND64mode +@item BND32mode BND64mode +These modes stand for bounds for pointer of 32 and 64 bit size respectively. +Mode size is double pointer mode size. @end table The machine description defines @code{Pmode} as a C macro which expands