--- /dev/null 2016-08-24 15:41:39.598575000 -0400 +++ new/hotspot/src/cpu/arm/vm/assembler_arm.hpp 2016-09-27 09:56:43.957845271 -0400 @@ -0,0 +1,404 @@ +/* + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_ARM_VM_ASSEMBLER_ARM_HPP +#define CPU_ARM_VM_ASSEMBLER_ARM_HPP + +#include "utilities/macros.hpp" + +enum AsmCondition { + eq, ne, cs, cc, mi, pl, vs, vc, + hi, ls, ge, lt, gt, le, al, nv, + number_of_conditions, + // alternative names + hs = cs, + lo = cc +}; + +enum AsmShift { + lsl, lsr, asr, ror +}; + +#ifdef AARCH64 +enum AsmExtendOp { + ex_uxtb, ex_uxth, ex_uxtw, ex_uxtx, + ex_sxtb, ex_sxth, ex_sxtw, ex_sxtx, + + ex_lsl = ex_uxtx +}; +#endif + +enum AsmOffset { +#ifdef AARCH64 + basic_offset = 0b00, + pre_indexed = 0b11, + post_indexed = 0b01 +#else + basic_offset = 1 << 24, + pre_indexed = 1 << 24 | 1 << 21, + post_indexed = 0 +#endif +}; + + +#ifndef AARCH64 +enum AsmWriteback { + no_writeback, + writeback +}; + +enum AsmOffsetOp { + sub_offset = 0, + add_offset = 1 +}; +#endif + + +// ARM Addressing Modes 2 and 3 - Load and store +class Address VALUE_OBJ_CLASS_SPEC { + private: + Register _base; + Register _index; + int _disp; + AsmOffset _mode; + RelocationHolder _rspec; + int _shift_imm; +#ifdef AARCH64 + AsmExtendOp _extend; +#else + AsmShift _shift; + AsmOffsetOp _offset_op; + + static inline int abs(int x) { return x < 0 ? -x : x; } + static inline int up (int x) { return x < 0 ? 0 : 1; } +#endif + +#ifdef AARCH64 + static const AsmExtendOp LSL = ex_lsl; +#else + static const AsmShift LSL = lsl; +#endif + + public: + Address() : _base(noreg) {} + + Address(Register rn, int offset = 0, AsmOffset mode = basic_offset) { + _base = rn; + _index = noreg; + _disp = offset; + _mode = mode; + _shift_imm = 0; +#ifdef AARCH64 + _extend = ex_lsl; +#else + _shift = lsl; + _offset_op = add_offset; +#endif + } + +#ifdef ASSERT + Address(Register rn, ByteSize offset, AsmOffset mode = basic_offset) { + _base = rn; + _index = noreg; + _disp = in_bytes(offset); + _mode = mode; + _shift_imm = 0; +#ifdef AARCH64 + _extend = ex_lsl; +#else + _shift = lsl; + _offset_op = add_offset; +#endif + } +#endif + +#ifdef AARCH64 + Address(Register rn, Register rm, AsmExtendOp extend = ex_lsl, int shift_imm = 0) { + assert ((extend == ex_uxtw) || (extend == ex_lsl) || (extend == ex_sxtw) || (extend == ex_sxtx), "invalid extend for address mode"); + assert ((0 <= shift_imm) && (shift_imm <= 4), "shift amount is out of range"); + _base = rn; + _index = rm; + _disp = 0; + _mode = basic_offset; + _extend = extend; + _shift_imm = shift_imm; + } +#else + Address(Register rn, Register rm, AsmShift shift = lsl, + int shift_imm = 0, AsmOffset mode = basic_offset, + AsmOffsetOp offset_op = add_offset) { + _base = rn; + _index = rm; + _disp = 0; + _shift = shift; + _shift_imm = shift_imm; + _mode = mode; + _offset_op = offset_op; + } + + Address(Register rn, RegisterOrConstant offset, AsmShift shift = lsl, + int shift_imm = 0) { + _base = rn; + if (offset.is_constant()) { + _index = noreg; + { + int off = (int) offset.as_constant(); + if (shift_imm != 0) { + assert(shift == lsl,"shift not yet encoded"); + off = off << shift_imm; + } + _disp = off; + } + _shift = lsl; + _shift_imm = 0; + } else { + _index = offset.as_register(); + _disp = 0; + _shift = shift; + _shift_imm = shift_imm; + } + _mode = basic_offset; + _offset_op = add_offset; + } +#endif // AARCH64 + + // [base + index * wordSize] + static Address indexed_ptr(Register base, Register index) { + return Address(base, index, LSL, LogBytesPerWord); + } + + // [base + index * BytesPerInt] + static Address indexed_32(Register base, Register index) { + return Address(base, index, LSL, LogBytesPerInt); + } + + // [base + index * BytesPerHeapOop] + static Address indexed_oop(Register base, Register index) { + return Address(base, index, LSL, LogBytesPerHeapOop); + } + + Address plus_disp(int disp) const { + assert((disp == 0) || (_index == noreg),"can't apply an offset to a register indexed address"); + Address a = (*this); + a._disp += disp; + return a; + } + + Address rebase(Register new_base) const { + Address a = (*this); + a._base = new_base; + return a; + } + +#ifdef AARCH64 + int encoding_simd() const { + assert(_index != SP, "encoding constraint"); + assert(_disp == 0 || _mode == post_indexed, "encoding constraint"); + assert(_index == noreg || _mode == basic_offset, "encoding constraint"); + assert(_mode == basic_offset || _mode == post_indexed, "encoding constraint"); + assert(_extend == ex_lsl, "encoding constraint"); + int index; + if (_index == noreg) { + if (_mode == post_indexed) + index = 0b100 << 5 | 31; + else + index = 0; + } else { + index = 0b100 << 5 | _index->encoding(); + } + return index << 16 | _base->encoding_with_sp() << 5; + } +#else /* !AARCH64 */ + int encoding2() const { + assert(_mode == basic_offset || _base != PC, "unpredictable instruction"); + if (_index == noreg) { + assert(-4096 < _disp && _disp < 4096, "encoding constraint"); + return _mode | up(_disp) << 23 | _base->encoding() << 16 | abs(_disp); + } else { + assert(_index != PC && (_mode == basic_offset || _index != _base), "unpredictable instruction"); + assert(_disp == 0 && (_shift_imm >> 5) == 0, "encoding constraint"); + return 1 << 25 | _offset_op << 23 | _mode | _base->encoding() << 16 | + _shift_imm << 7 | _shift << 5 | _index->encoding(); + } + } + + int encoding3() const { + assert(_mode == basic_offset || _base != PC, "unpredictable instruction"); + if (_index == noreg) { + assert(-256 < _disp && _disp < 256, "encoding constraint"); + return _mode | up(_disp) << 23 | 1 << 22 | _base->encoding() << 16 | + (abs(_disp) & 0xf0) << 4 | abs(_disp) & 0x0f; + } else { + assert(_index != PC && (_mode == basic_offset || _index != _base), "unpredictable instruction"); + assert(_disp == 0 && _shift == lsl && _shift_imm == 0, "encoding constraint"); + return _mode | _offset_op << 23 | _base->encoding() << 16 | _index->encoding(); + } + } + + int encoding_ex() const { + assert(_index == noreg && _disp == 0 && _mode == basic_offset && + _base != PC, "encoding constraint"); + return _base->encoding() << 16; + } + + int encoding_vfp() const { + assert(_index == noreg && _mode == basic_offset, "encoding constraint"); + assert(-1024 < _disp && _disp < 1024 && (_disp & 3) == 0, "encoding constraint"); + return _base->encoding() << 16 | up(_disp) << 23 | abs(_disp) >> 2; + } + + int encoding_simd() const { + assert(_base != PC, "encoding constraint"); + assert(_index != PC && _index != SP, "encoding constraint"); + assert(_disp == 0, "encoding constraint"); + assert(_shift == 0, "encoding constraint"); + assert(_index == noreg || _mode == basic_offset, "encoding constraint"); + assert(_mode == basic_offset || _mode == post_indexed, "encoding constraint"); + int index; + if (_index == noreg) { + if (_mode == post_indexed) + index = 13; + else + index = 15; + } else { + index = _index->encoding(); + } + + return _base->encoding() << 16 | index; + } +#endif // !AARCH64 + + Register base() const { + return _base; + } + + Register index() const { + return _index; + } + + int disp() const { + return _disp; + } + + AsmOffset mode() const { + return _mode; + } + + int shift_imm() const { + return _shift_imm; + } + +#ifdef AARCH64 + AsmExtendOp extend() const { + return _extend; + } +#else + AsmShift shift() const { + return _shift; + } + + AsmOffsetOp offset_op() const { + return _offset_op; + } +#endif + + bool uses(Register reg) const { return _base == reg || _index == reg; } + + const relocInfo::relocType rtype() { return _rspec.type(); } + const RelocationHolder& rspec() { return _rspec; } + + // Convert the raw encoding form into the form expected by the + // constructor for Address. + static Address make_raw(int base, int index, int scale, int disp, relocInfo::relocType disp_reloc); +}; + +#ifdef COMPILER2 +class VFP VALUE_OBJ_CLASS_SPEC { + // Helper classes to detect whether a floating point constant can be + // encoded in a fconstd or fconsts instruction + // The conversion from the imm8, 8 bit constant, to the floating + // point value encoding is done with either: + // for single precision: imm8<7>:NOT(imm8<6>):Replicate(imm8<6>,5):imm8<5:0>:Zeros(19) + // or + // for double precision: imm8<7>:NOT(imm8<6>):Replicate(imm8<6>,8):imm8<5:0>:Zeros(48) + + private: + class fpnum { + public: + virtual unsigned int f_hi4() const = 0; + virtual bool f_lo_is_null() const = 0; + virtual int e() const = 0; + virtual unsigned int s() const = 0; + + inline bool can_be_imm8() const { return e() >= -3 && e() <= 4 && f_lo_is_null(); } + inline unsigned char imm8() const { int v = (s() << 7) | (((e() - 1) & 0x7) << 4) | f_hi4(); assert((v >> 8) == 0, "overflow"); return v; } + }; + + public: + class float_num : public fpnum { + public: + float_num(float v) { + _num.val = v; + } + + virtual unsigned int f_hi4() const { return (_num.bits << 9) >> (19+9); } + virtual bool f_lo_is_null() const { return (_num.bits & ((1 << 19) - 1)) == 0; } + virtual int e() const { return ((_num.bits << 1) >> (23+1)) - 127; } + virtual unsigned int s() const { return _num.bits >> 31; } + + private: + union { + float val; + unsigned int bits; + } _num; + }; + + class double_num : public fpnum { + public: + double_num(double v) { + _num.val = v; + } + + virtual unsigned int f_hi4() const { return (_num.bits << 12) >> (48+12); } + virtual bool f_lo_is_null() const { return (_num.bits & ((1LL << 48) - 1)) == 0; } + virtual int e() const { return ((_num.bits << 1) >> (52+1)) - 1023; } + virtual unsigned int s() const { return _num.bits >> 63; } + + private: + union { + double val; + unsigned long long bits; + } _num; + }; +}; +#endif + +#ifdef AARCH64 +#include "assembler_arm_64.hpp" +#else +#include "assembler_arm_32.hpp" +#endif + + +#endif // CPU_ARM_VM_ASSEMBLER_ARM_HPP