Path: blob/master/src/hotspot/cpu/arm/assembler_arm.hpp
40930 views
/*1* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef CPU_ARM_ASSEMBLER_ARM_HPP25#define CPU_ARM_ASSEMBLER_ARM_HPP2627#include "utilities/macros.hpp"2829enum AsmCondition {30eq, ne, cs, cc, mi, pl, vs, vc,31hi, ls, ge, lt, gt, le, al, nv,32number_of_conditions,33// alternative names34hs = cs,35lo = cc36};3738enum AsmShift {39lsl, lsr, asr, ror40};414243enum AsmOffset {44basic_offset = 1 << 24,45pre_indexed = 1 << 24 | 1 << 21,46post_indexed = 047};484950enum AsmWriteback {51no_writeback,52writeback53};5455enum AsmOffsetOp {56sub_offset = 0,57add_offset = 158};596061// ARM Addressing Modes 2 and 3 - Load and store62class Address {63private:64Register _base;65Register _index;66int _disp;67AsmOffset _mode;68RelocationHolder _rspec;69int _shift_imm;70AsmShift _shift;71AsmOffsetOp _offset_op;7273static inline int abs(int x) { return x < 0 ? -x : x; }74static inline int up (int x) { return x < 0 ? 0 : 1; }7576static const AsmShift LSL = lsl;7778public:79Address() : _base(noreg) {}8081Address(Register rn, int offset = 0, AsmOffset mode = basic_offset) {82_base = rn;83_index = noreg;84_disp = offset;85_mode = mode;86_shift_imm = 0;87_shift = lsl;88_offset_op = add_offset;89}9091Address(Register rn, ByteSize offset, AsmOffset mode = basic_offset) :92Address(rn, in_bytes(offset), mode) {}9394Address(Register rn, Register rm, AsmShift shift = lsl,95int shift_imm = 0, AsmOffset mode = basic_offset,96AsmOffsetOp offset_op = add_offset) {97_base = rn;98_index = rm;99_disp = 0;100_shift = shift;101_shift_imm = shift_imm;102_mode = mode;103_offset_op = offset_op;104}105106Address(Register rn, RegisterOrConstant offset, AsmShift shift = lsl,107int shift_imm = 0) {108_base = rn;109if (offset.is_constant()) {110_index = noreg;111{112int off = (int) offset.as_constant();113if (shift_imm != 0) {114assert(shift == lsl,"shift not yet encoded");115off = off << shift_imm;116}117_disp = off;118}119_shift = lsl;120_shift_imm = 0;121} else {122_index = offset.as_register();123_disp = 0;124_shift = shift;125_shift_imm = shift_imm;126}127_mode = basic_offset;128_offset_op = add_offset;129}130131// [base + index * wordSize]132static Address indexed_ptr(Register base, Register index) {133return Address(base, index, LSL, LogBytesPerWord);134}135136// [base + index * BytesPerInt]137static Address indexed_32(Register base, Register index) {138return Address(base, index, LSL, LogBytesPerInt);139}140141// [base + index * BytesPerHeapOop]142static Address indexed_oop(Register base, Register index) {143return Address(base, index, LSL, LogBytesPerHeapOop);144}145146Address plus_disp(int disp) const {147assert((disp == 0) || (_index == noreg),"can't apply an offset to a register indexed address");148Address a = (*this);149a._disp += disp;150return a;151}152153Address rebase(Register new_base) const {154Address a = (*this);155a._base = new_base;156return a;157}158159int encoding2() const {160assert(_mode == basic_offset || _base != PC, "unpredictable instruction");161if (_index == noreg) {162assert(-4096 < _disp && _disp < 4096, "encoding constraint");163return _mode | up(_disp) << 23 | _base->encoding() << 16 | abs(_disp);164} else {165assert(_index != PC && (_mode == basic_offset || _index != _base), "unpredictable instruction");166assert(_disp == 0 && (_shift_imm >> 5) == 0, "encoding constraint");167return 1 << 25 | _offset_op << 23 | _mode | _base->encoding() << 16 |168_shift_imm << 7 | _shift << 5 | _index->encoding();169}170}171172int encoding3() const {173assert(_mode == basic_offset || _base != PC, "unpredictable instruction");174if (_index == noreg) {175assert(-256 < _disp && _disp < 256, "encoding constraint");176return _mode | up(_disp) << 23 | 1 << 22 | _base->encoding() << 16 |177(abs(_disp) & 0xf0) << 4 | abs(_disp) & 0x0f;178} else {179assert(_index != PC && (_mode == basic_offset || _index != _base), "unpredictable instruction");180assert(_disp == 0 && _shift == lsl && _shift_imm == 0, "encoding constraint");181return _mode | _offset_op << 23 | _base->encoding() << 16 | _index->encoding();182}183}184185int encoding_ex() const {186assert(_index == noreg && _disp == 0 && _mode == basic_offset &&187_base != PC, "encoding constraint");188return _base->encoding() << 16;189}190191int encoding_vfp() const {192assert(_index == noreg && _mode == basic_offset, "encoding constraint");193assert(-1024 < _disp && _disp < 1024 && (_disp & 3) == 0, "encoding constraint");194return _base->encoding() << 16 | up(_disp) << 23 | abs(_disp) >> 2;195}196197int encoding_simd() const {198assert(_base != PC, "encoding constraint");199assert(_index != PC && _index != SP, "encoding constraint");200assert(_disp == 0, "encoding constraint");201assert(_shift == 0, "encoding constraint");202assert(_index == noreg || _mode == basic_offset, "encoding constraint");203assert(_mode == basic_offset || _mode == post_indexed, "encoding constraint");204int index;205if (_index == noreg) {206if (_mode == post_indexed)207index = 13;208else209index = 15;210} else {211index = _index->encoding();212}213214return _base->encoding() << 16 | index;215}216217Register base() const {218return _base;219}220221Register index() const {222return _index;223}224225int disp() const {226return _disp;227}228229AsmOffset mode() const {230return _mode;231}232233int shift_imm() const {234return _shift_imm;235}236237AsmShift shift() const {238return _shift;239}240241AsmOffsetOp offset_op() const {242return _offset_op;243}244245bool uses(Register reg) const { return _base == reg || _index == reg; }246247const relocInfo::relocType rtype() { return _rspec.type(); }248const RelocationHolder& rspec() { return _rspec; }249250// Convert the raw encoding form into the form expected by the251// constructor for Address.252static Address make_raw(int base, int index, int scale, int disp, relocInfo::relocType disp_reloc);253};254255#ifdef COMPILER2256class VFP {257// Helper classes to detect whether a floating point constant can be258// encoded in a fconstd or fconsts instruction259// The conversion from the imm8, 8 bit constant, to the floating260// point value encoding is done with either:261// for single precision: imm8<7>:NOT(imm8<6>):Replicate(imm8<6>,5):imm8<5:0>:Zeros(19)262// or263// for double precision: imm8<7>:NOT(imm8<6>):Replicate(imm8<6>,8):imm8<5:0>:Zeros(48)264265private:266class fpnum {267public:268virtual unsigned int f_hi4() const = 0;269virtual bool f_lo_is_null() const = 0;270virtual int e() const = 0;271virtual unsigned int s() const = 0;272273inline bool can_be_imm8() const { return e() >= -3 && e() <= 4 && f_lo_is_null(); }274inline unsigned char imm8() const { int v = (s() << 7) | (((e() - 1) & 0x7) << 4) | f_hi4(); assert((v >> 8) == 0, "overflow"); return v; }275};276277public:278class float_num : public fpnum {279public:280float_num(float v) {281_num.val = v;282}283284virtual unsigned int f_hi4() const { return (_num.bits << 9) >> (19+9); }285virtual bool f_lo_is_null() const { return (_num.bits & ((1 << 19) - 1)) == 0; }286virtual int e() const { return ((_num.bits << 1) >> (23+1)) - 127; }287virtual unsigned int s() const { return _num.bits >> 31; }288289private:290union {291float val;292unsigned int bits;293} _num;294};295296class double_num : public fpnum {297public:298double_num(double v) {299_num.val = v;300}301302virtual unsigned int f_hi4() const { return (_num.bits << 12) >> (48+12); }303virtual bool f_lo_is_null() const { return (_num.bits & ((1LL << 48) - 1)) == 0; }304virtual int e() const { return ((_num.bits << 1) >> (52+1)) - 1023; }305virtual unsigned int s() const { return _num.bits >> 63; }306307private:308union {309double val;310unsigned long long bits;311} _num;312};313};314#endif315316#include "assembler_arm_32.hpp"317318319#endif // CPU_ARM_ASSEMBLER_ARM_HPP320321322