--- old/src/cpu/x86/vm/assembler_x86.hpp 2015-10-29 10:25:16.624979500 -0700 +++ new/src/cpu/x86/vm/assembler_x86.hpp 2015-10-29 10:25:16.406979500 -0700 @@ -438,6 +438,8 @@ }; +class InstructionAttr; + // 64-bit refect the fxsave size which is 512 bytes and the new xsave area on EVEX which is another 2176 bytes // See fxsave and xsave(EVEX enabled) documentation for layout const int FPUStateSizeInWords = NOT_LP64(27) LP64_ONLY(2688 / wordSize); @@ -568,7 +570,8 @@ EVEX_8bit = 0, EVEX_16bit = 1, EVEX_32bit = 2, - EVEX_64bit = 3 + EVEX_64bit = 3, + EVEX_NObit = 4 }; enum WhichOperand { @@ -598,16 +601,12 @@ private: - int _evex_encoding; - int _input_size_in_bits; - int _avx_vector_len; - int _tuple_type; - bool _is_evex_instruction; bool _legacy_mode_bw; bool _legacy_mode_dq; bool _legacy_mode_vl; bool _legacy_mode_vlbw; - bool _instruction_uses_vl; + + class InstructionAttr *_attributes; // 64bit prefixes int prefix_and_encode(int reg_enc, bool byteinst = false); @@ -637,181 +636,30 @@ int rex_prefix_and_encode(int dst_enc, int src_enc, VexSimdPrefix pre, VexOpcode opc, bool rex_w); - void vex_prefix(bool vex_r, bool vex_b, bool vex_x, bool vex_w, - int nds_enc, VexSimdPrefix pre, VexOpcode opc, - int vector_len); - - void evex_prefix(bool vex_r, bool vex_b, bool vex_x, bool vex_w, bool evex_r, bool evex_v, - int nds_enc, VexSimdPrefix pre, VexOpcode opc, - bool is_extended_context, bool is_merge_context, - int vector_len, bool no_mask_reg ); + void vex_prefix(bool vex_r, bool vex_b, bool vex_x, int nds_enc, VexSimdPrefix pre, VexOpcode opc); + + void evex_prefix(bool vex_r, bool vex_b, bool vex_x, bool evex_r, bool evex_v, + int nds_enc, VexSimdPrefix pre, VexOpcode opc); void vex_prefix(Address adr, int nds_enc, int xreg_enc, VexSimdPrefix pre, VexOpcode opc, - bool vex_w, int vector_len, - bool legacy_mode = false, bool no_mask_reg = false); - - void vex_prefix(XMMRegister dst, XMMRegister nds, Address src, - VexSimdPrefix pre, int vector_len = AVX_128bit, - bool no_mask_reg = false, bool legacy_mode = false) { - int dst_enc = dst->encoding(); - int nds_enc = nds->is_valid() ? nds->encoding() : 0; - vex_prefix(src, nds_enc, dst_enc, pre, VEX_OPCODE_0F, false, vector_len, legacy_mode, no_mask_reg); - } - - void vex_prefix_q(XMMRegister dst, XMMRegister nds, Address src, - VexSimdPrefix pre, int vector_len = AVX_128bit, - bool no_mask_reg = false) { - int dst_enc = dst->encoding(); - int nds_enc = nds->is_valid() ? nds->encoding() : 0; - vex_prefix(src, nds_enc, dst_enc, pre, VEX_OPCODE_0F, true, vector_len, false, no_mask_reg); - } - - void vex_prefix_0F38(Register dst, Register nds, Address src, bool no_mask_reg = false) { - bool vex_w = false; - int vector_len = AVX_128bit; - vex_prefix(src, nds->encoding(), dst->encoding(), - VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, - vector_len, no_mask_reg); - } - - void vex_prefix_0F38_legacy(Register dst, Register nds, Address src, bool no_mask_reg = false) { - bool vex_w = false; - int vector_len = AVX_128bit; - vex_prefix(src, nds->encoding(), dst->encoding(), - VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, - vector_len, true, no_mask_reg); - } - - void vex_prefix_0F38_q(Register dst, Register nds, Address src, bool no_mask_reg = false) { - bool vex_w = true; - int vector_len = AVX_128bit; - vex_prefix(src, nds->encoding(), dst->encoding(), - VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, - vector_len, no_mask_reg); - } - - void vex_prefix_0F38_q_legacy(Register dst, Register nds, Address src, bool no_mask_reg = false) { - bool vex_w = true; - int vector_len = AVX_128bit; - vex_prefix(src, nds->encoding(), dst->encoding(), - VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, - vector_len, true, no_mask_reg); - } + InstructionAttr *attributes); int vex_prefix_and_encode(int dst_enc, int nds_enc, int src_enc, VexSimdPrefix pre, VexOpcode opc, - bool vex_w, int vector_len, - bool legacy_mode, bool no_mask_reg); - - int vex_prefix_0F38_and_encode(Register dst, Register nds, Register src, bool no_mask_reg = false) { - bool vex_w = false; - int vector_len = AVX_128bit; - return vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), - VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector_len, - false, no_mask_reg); - } + InstructionAttr *attributes); - int vex_prefix_0F38_and_encode_legacy(Register dst, Register nds, Register src, bool no_mask_reg = false) { - bool vex_w = false; - int vector_len = AVX_128bit; - return vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), - VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector_len, - true, no_mask_reg); - } - - int vex_prefix_0F38_and_encode_q(Register dst, Register nds, Register src, bool no_mask_reg = false) { - bool vex_w = true; - int vector_len = AVX_128bit; - return vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), - VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector_len, - false, no_mask_reg); - } + void simd_prefix(XMMRegister xreg, XMMRegister nds, Address adr, VexSimdPrefix pre, + VexOpcode opc, InstructionAttr *attributes); - int vex_prefix_0F38_and_encode_q_legacy(Register dst, Register nds, Register src, bool no_mask_reg = false) { - bool vex_w = true; - int vector_len = AVX_128bit; - return vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), - VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector_len, - true, no_mask_reg); - } + int simd_prefix_and_encode(XMMRegister dst, XMMRegister nds, XMMRegister src, VexSimdPrefix pre, + VexOpcode opc, InstructionAttr *attributes); - int vex_prefix_and_encode(XMMRegister dst, XMMRegister nds, XMMRegister src, - VexSimdPrefix pre, int vector_len = AVX_128bit, - VexOpcode opc = VEX_OPCODE_0F, bool legacy_mode = false, - bool no_mask_reg = false) { - int src_enc = src->encoding(); - int dst_enc = dst->encoding(); - int nds_enc = nds->is_valid() ? nds->encoding() : 0; - return vex_prefix_and_encode(dst_enc, nds_enc, src_enc, pre, opc, false, vector_len, legacy_mode, no_mask_reg); - } + int kreg_prefix_and_encode(KRegister dst, KRegister nds, KRegister src, VexSimdPrefix pre, + VexOpcode opc, InstructionAttr *attributes); - void simd_prefix(XMMRegister xreg, XMMRegister nds, Address adr, - VexSimdPrefix pre, bool no_mask_reg, VexOpcode opc = VEX_OPCODE_0F, - bool rex_w = false, int vector_len = AVX_128bit, bool legacy_mode = false); - - void simd_prefix(XMMRegister dst, Address src, VexSimdPrefix pre, - bool no_mask_reg, VexOpcode opc = VEX_OPCODE_0F) { - simd_prefix(dst, xnoreg, src, pre, no_mask_reg, opc); - } - - void simd_prefix(Address dst, XMMRegister src, VexSimdPrefix pre, bool no_mask_reg) { - simd_prefix(src, dst, pre, no_mask_reg); - } - void simd_prefix_q(XMMRegister dst, XMMRegister nds, Address src, - VexSimdPrefix pre, bool no_mask_reg = false) { - bool rex_w = true; - simd_prefix(dst, nds, src, pre, no_mask_reg, VEX_OPCODE_0F, rex_w); - } - - int simd_prefix_and_encode(XMMRegister dst, XMMRegister nds, XMMRegister src, - VexSimdPrefix pre, bool no_mask_reg, - VexOpcode opc = VEX_OPCODE_0F, - bool rex_w = false, int vector_len = AVX_128bit, - bool legacy_mode = false); - - int kreg_prefix_and_encode(KRegister dst, KRegister nds, KRegister src, - VexSimdPrefix pre, bool no_mask_reg, - VexOpcode opc = VEX_OPCODE_0F, - bool rex_w = false, int vector_len = AVX_128bit); - - int kreg_prefix_and_encode(KRegister dst, KRegister nds, Register src, - VexSimdPrefix pre, bool no_mask_reg, - VexOpcode opc = VEX_OPCODE_0F, - bool rex_w = false, int vector_len = AVX_128bit); - - // Move/convert 32-bit integer value. - int simd_prefix_and_encode(XMMRegister dst, XMMRegister nds, Register src, - VexSimdPrefix pre, bool no_mask_reg) { - // It is OK to cast from Register to XMMRegister to pass argument here - // since only encoding is used in simd_prefix_and_encode() and number of - // Gen and Xmm registers are the same. - return simd_prefix_and_encode(dst, nds, as_XMMRegister(src->encoding()), pre, no_mask_reg, VEX_OPCODE_0F); - } - int simd_prefix_and_encode(XMMRegister dst, Register src, VexSimdPrefix pre, bool no_mask_reg) { - return simd_prefix_and_encode(dst, xnoreg, src, pre, no_mask_reg); - } - int simd_prefix_and_encode(Register dst, XMMRegister src, - VexSimdPrefix pre, VexOpcode opc = VEX_OPCODE_0F, - bool no_mask_reg = false) { - return simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, pre, no_mask_reg, opc); - } - - // Move/convert 64-bit integer value. - int simd_prefix_and_encode_q(XMMRegister dst, XMMRegister nds, Register src, - VexSimdPrefix pre, bool no_mask_reg = false) { - bool rex_w = true; - return simd_prefix_and_encode(dst, nds, as_XMMRegister(src->encoding()), pre, no_mask_reg, VEX_OPCODE_0F, rex_w); - } - int simd_prefix_and_encode_q(XMMRegister dst, Register src, VexSimdPrefix pre, bool no_mask_reg) { - return simd_prefix_and_encode_q(dst, xnoreg, src, pre, no_mask_reg); - } - int simd_prefix_and_encode_q(Register dst, XMMRegister src, - VexSimdPrefix pre, VexOpcode opc = VEX_OPCODE_0F, - bool no_mask_reg = false) { - bool rex_w = true; - return simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, pre, no_mask_reg, opc, rex_w); - } + int kreg_prefix_and_encode(KRegister dst, KRegister nds, Register src, VexSimdPrefix pre, + VexOpcode opc, InstructionAttr *attributes); // Helper functions for groups of instructions void emit_arith_b(int op1, int op2, Register dst, int imm8); @@ -821,27 +669,6 @@ void emit_arith_imm32(int op1, int op2, Register dst, int32_t imm32); void emit_arith(int op1, int op2, Register dst, Register src); - void emit_simd_arith(int opcode, XMMRegister dst, Address src, VexSimdPrefix pre, bool no_mask_reg = false, bool legacy_mode = false); - void emit_simd_arith_q(int opcode, XMMRegister dst, Address src, VexSimdPrefix pre, bool no_mask_reg = false); - void emit_simd_arith(int opcode, XMMRegister dst, XMMRegister src, VexSimdPrefix pre, bool no_mask_reg = false, bool legacy_mode = false); - void emit_simd_arith_q(int opcode, XMMRegister dst, XMMRegister src, VexSimdPrefix pre, bool no_mask_reg = false); - void emit_simd_arith_nonds(int opcode, XMMRegister dst, Address src, VexSimdPrefix pre, bool no_mask_reg = false); - void emit_simd_arith_nonds_q(int opcode, XMMRegister dst, Address src, VexSimdPrefix pre, bool no_mask_reg = false); - void emit_simd_arith_nonds(int opcode, XMMRegister dst, XMMRegister src, VexSimdPrefix pre, bool no_mask_reg = false, bool legacy_mode = false); - void emit_simd_arith_nonds_q(int opcode, XMMRegister dst, XMMRegister src, VexSimdPrefix pre, bool no_mask_reg = false); - void emit_vex_arith(int opcode, XMMRegister dst, XMMRegister nds, - Address src, VexSimdPrefix pre, int vector_len, - bool no_mask_reg = false, bool legacy_mode = false); - void emit_vex_arith_q(int opcode, XMMRegister dst, XMMRegister nds, - Address src, VexSimdPrefix pre, int vector_len, - bool no_mask_reg = false); - void emit_vex_arith(int opcode, XMMRegister dst, XMMRegister nds, - XMMRegister src, VexSimdPrefix pre, int vector_len, - bool no_mask_reg = false, bool legacy_mode = false); - void emit_vex_arith_q(int opcode, XMMRegister dst, XMMRegister nds, - XMMRegister src, VexSimdPrefix pre, int vector_len, - bool no_mask_reg = false); - bool emit_compressed_disp_byte(int &disp); void emit_operand(Register reg, @@ -986,18 +813,16 @@ // belong in macro assembler but there is no need for both varieties to exist void init_attributes(void) { - _evex_encoding = 0; - _input_size_in_bits = 0; - _avx_vector_len = AVX_NoVec; - _tuple_type = EVEX_ETUP; - _is_evex_instruction = false; _legacy_mode_bw = (VM_Version::supports_avx512bw() == false); _legacy_mode_dq = (VM_Version::supports_avx512dq() == false); _legacy_mode_vl = (VM_Version::supports_avx512vl() == false); _legacy_mode_vlbw = (VM_Version::supports_avx512vlbw() == false); - _instruction_uses_vl = false; + _attributes = NULL; } + void set_attributes(InstructionAttr *attributes) { _attributes = attributes; } + void clear_attributes(void) { _attributes = NULL; } + void lea(Register dst, Address src); void mov(Register dst, Register src); @@ -2098,12 +1923,12 @@ void vextracti128h(Address dst, XMMRegister src); // Copy low 256bit into high 256bit of ZMM registers. - void vinserti64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src); - void vinsertf64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src); - void vextracti64x4h(XMMRegister dst, XMMRegister src); - void vextractf64x4h(XMMRegister dst, XMMRegister src); - void vextractf64x4h(Address dst, XMMRegister src); - void vinsertf64x4h(XMMRegister dst, Address src); + void vinserti64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value); + void vinsertf64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value); + void vextracti64x4h(XMMRegister dst, XMMRegister src, int value); + void vextractf64x4h(XMMRegister dst, XMMRegister src, int value); + void vextractf64x4h(Address dst, XMMRegister src, int value); + void vinsertf64x4h(XMMRegister dst, Address src, int value); // Copy targeted 128bit segments of the ZMM registers void vextracti64x2h(XMMRegister dst, XMMRegister src, int value); @@ -2162,4 +1987,95 @@ }; +// The Intel x86/Amd64 Assembler attributes: All fields enclosed here are to guide encoding level decisions. +// Specific set functions are for specialized use, else defaults or whatever was supplied to object construction +// are applied. +class InstructionAttr { +public: + InstructionAttr( + int vector_len, + bool rex_vex_w, + bool legacy_mode, + bool no_reg_mask, + bool uses_vl) + : + _avx_vector_len(vector_len), + _rex_vex_w(rex_vex_w), + _legacy_mode(legacy_mode), + _no_reg_mask(no_reg_mask), + _uses_vl(uses_vl), + _tuple_type(Assembler::EVEX_ETUP), + _input_size_in_bits(Assembler::EVEX_NObit), + _is_evex_instruction(false), + _evex_encoding(0), + _is_clear_context(false), + _is_extended_context(false), + _current_assembler(NULL) { + if (UseAVX < 3) _legacy_mode = true; + } + + ~InstructionAttr() { + if (_current_assembler != NULL) { + _current_assembler->clear_attributes(); + } + _current_assembler = NULL; + } + +private: + int _avx_vector_len; + bool _rex_vex_w; + bool _legacy_mode; + bool _no_reg_mask; + bool _uses_vl; + int _tuple_type; + int _input_size_in_bits; + bool _is_evex_instruction; + int _evex_encoding; + bool _is_clear_context; + bool _is_extended_context; + + Assembler *_current_assembler; + +public: + // query functions for field accessors + int get_vector_len(void) const { return _avx_vector_len; } + bool is_rex_vex_w(void) const { return _rex_vex_w; } + bool is_legacy_mode(void) const { return _legacy_mode; } + bool is_no_reg_mask(void) const { return _no_reg_mask; } + bool uses_vl(void) const { return _uses_vl; } + int get_tuple_type(void) const { return _tuple_type; } + int get_input_size(void) const { return _input_size_in_bits; } + int is_evex_instruction(void) const { return _is_evex_instruction; } + int get_evex_encoding(void) const { return _evex_encoding; } + bool is_clear_context(void) const { return _is_clear_context; } + bool is_extended_context(void) const { return _is_extended_context; } + + // Set the vector len manually + void set_vector_len(int vector_len) { _avx_vector_len = vector_len; } + + // Set the instruction to be encoded in AVX mode + void set_is_legacy_mode(void) { _legacy_mode = true; } + + // Set the current instuction to be encoded as an EVEX instuction + void set_is_evex_instruction(void) { _is_evex_instruction = true; } + + // Internal encoding data used in compressed immediate offset programming + void set_evex_encoding(int value) { _evex_encoding = value; } + + // Set the Evex.Z field to be used to clear all non directed XMM/YMM/ZMM components + void set_is_clear_context(void) { _is_clear_context = true; } + + // Map back to current asembler so that we can manage object level assocation + void set_current_assembler(Assembler *current_assembler) { _current_assembler = current_assembler; } + + // Address modifiers used for compressed displacement calculation + void set_address_attributes(int tuple_type, int input_size_in_bits) { + if (VM_Version::supports_evex()) { + _tuple_type = tuple_type; + _input_size_in_bits = input_size_in_bits; + } + } + +}; + #endif // CPU_X86_VM_ASSEMBLER_X86_HPP