< prev index next >

src/cpu/x86/vm/assembler_x86.hpp

Print this page

        

*** 436,445 **** --- 436,447 ---- AddressLiteral base() { return _base; } Address index() { return _index; } }; + 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); // The Intel x86/Amd64 Assembler: Pure assembler doing NO optimizations on the instruction
*** 566,576 **** enum EvexInputSizeInBits { EVEX_8bit = 0, EVEX_16bit = 1, EVEX_32bit = 2, ! EVEX_64bit = 3 }; enum WhichOperand { // input to locate_operand, and format code for relocations imm_operand = 0, // embedded 32-bit|64-bit immediate operand --- 568,579 ---- enum EvexInputSizeInBits { EVEX_8bit = 0, EVEX_16bit = 1, EVEX_32bit = 2, ! EVEX_64bit = 3, ! EVEX_NObit = 4 }; enum WhichOperand { // input to locate_operand, and format code for relocations imm_operand = 0, // embedded 32-bit|64-bit immediate operand
*** 596,615 **** // This does mean you'll get a linker/runtime error if you use a 64bit only instruction // in a 32bit vm. This is somewhat unfortunate but keeps the ifdef noise down. 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; // 64bit prefixes int prefix_and_encode(int reg_enc, bool byteinst = false); int prefixq_and_encode(int reg_enc); --- 599,614 ---- // This does mean you'll get a linker/runtime error if you use a 64bit only instruction // in a 32bit vm. This is somewhat unfortunate but keeps the ifdef noise down. private: bool _legacy_mode_bw; bool _legacy_mode_dq; bool _legacy_mode_vl; bool _legacy_mode_vlbw; ! ! class InstructionAttr *_attributes; // 64bit prefixes int prefix_and_encode(int reg_enc, bool byteinst = false); int prefixq_and_encode(int reg_enc);
*** 635,849 **** void rex_prefix(Address adr, XMMRegister xreg, VexSimdPrefix pre, VexOpcode opc, bool rex_w); 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(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); ! } 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); ! } ! 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); ! } ! 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 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); ! } ! ! 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); ! } // Helper functions for groups of instructions void emit_arith_b(int op1, int op2, Register dst, int imm8); void emit_arith(int op1, int op2, Register dst, int32_t imm32); // Force generation of a 4 byte immediate value even if it fits into 8bit 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, Register base, Register index, Address::ScaleFactor scale, int disp, --- 634,676 ---- void rex_prefix(Address adr, XMMRegister xreg, VexSimdPrefix pre, VexOpcode opc, bool rex_w); 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, 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, ! InstructionAttr *attributes); int vex_prefix_and_encode(int dst_enc, int nds_enc, int src_enc, VexSimdPrefix pre, VexOpcode opc, ! InstructionAttr *attributes); ! void simd_prefix(XMMRegister xreg, XMMRegister nds, Address adr, VexSimdPrefix pre, ! VexOpcode opc, InstructionAttr *attributes); ! int simd_prefix_and_encode(XMMRegister dst, XMMRegister nds, XMMRegister src, VexSimdPrefix pre, ! VexOpcode opc, InstructionAttr *attributes); ! int kreg_prefix_and_encode(KRegister dst, KRegister nds, KRegister src, VexSimdPrefix pre, ! VexOpcode opc, InstructionAttr *attributes); ! 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); void emit_arith(int op1, int op2, Register dst, int32_t imm32); // Force generation of a 4 byte immediate value even if it fits into 8bit void emit_arith_imm32(int op1, int op2, Register dst, int32_t imm32); void emit_arith(int op1, int op2, Register dst, Register src); bool emit_compressed_disp_byte(int &disp); void emit_operand(Register reg, Register base, Register index, Address::ScaleFactor scale, int disp,
*** 984,1005 **** // Generic instructions // Does 32bit or 64bit as needed for the platform. In some sense these // 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; } void lea(Register dst, Address src); void mov(Register dst, Register src); void pusha(); --- 811,830 ---- // Generic instructions // Does 32bit or 64bit as needed for the platform. In some sense these // belong in macro assembler but there is no need for both varieties to exist void init_attributes(void) { _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); ! _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); void pusha();
*** 2096,2111 **** void vinserti128h(XMMRegister dst, Address src); void vextractf128h(Address dst, XMMRegister src); 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); // Copy targeted 128bit segments of the ZMM registers void vextracti64x2h(XMMRegister dst, XMMRegister src, int value); void vextractf64x2h(XMMRegister dst, XMMRegister src, int value); void vextractf32x4h(XMMRegister dst, XMMRegister src, int value); --- 1921,1936 ---- void vinserti128h(XMMRegister dst, Address src); void vextractf128h(Address dst, XMMRegister src); void vextracti128h(Address dst, XMMRegister src); // Copy low 256bit into high 256bit of ZMM registers. ! 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); void vextractf64x2h(XMMRegister dst, XMMRegister src, int value); void vextractf32x4h(XMMRegister dst, XMMRegister src, int value);
*** 2160,2165 **** --- 1985,2081 ---- void xorpd(XMMRegister dst, Address src); void xorps(XMMRegister dst, Address src); }; + // 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
< prev index next >