1 /* 2 * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef CPU_ARM_VM_ASSEMBLER_ARM_HPP 26 #define CPU_ARM_VM_ASSEMBLER_ARM_HPP 27 28 #include "utilities/macros.hpp" 29 30 enum AsmCondition { 31 eq, ne, cs, cc, mi, pl, vs, vc, 32 hi, ls, ge, lt, gt, le, al, nv, 33 number_of_conditions, 34 // alternative names 35 hs = cs, 36 lo = cc 37 }; 38 39 enum AsmShift { 40 lsl, lsr, asr, ror 41 }; 42 43 44 enum AsmOffset { 45 basic_offset = 1 << 24, 46 pre_indexed = 1 << 24 | 1 << 21, 47 post_indexed = 0 48 }; 49 50 51 enum AsmWriteback { 52 no_writeback, 53 writeback 54 }; 55 56 enum AsmOffsetOp { 57 sub_offset = 0, 58 add_offset = 1 59 }; 60 61 62 // ARM Addressing Modes 2 and 3 - Load and store 63 class Address { 64 private: 65 Register _base; 66 Register _index; 67 int _disp; 68 AsmOffset _mode; 69 RelocationHolder _rspec; 70 int _shift_imm; 71 AsmShift _shift; 72 AsmOffsetOp _offset_op; 73 abs(int x)74 static inline int abs(int x) { return x < 0 ? -x : x; } up(int x)75 static inline int up (int x) { return x < 0 ? 0 : 1; } 76 77 static const AsmShift LSL = lsl; 78 79 public: Address()80 Address() : _base(noreg) {} 81 Address(Register rn,int offset=0,AsmOffset mode=basic_offset)82 Address(Register rn, int offset = 0, AsmOffset mode = basic_offset) { 83 _base = rn; 84 _index = noreg; 85 _disp = offset; 86 _mode = mode; 87 _shift_imm = 0; 88 _shift = lsl; 89 _offset_op = add_offset; 90 } 91 92 #ifdef ASSERT Address(Register rn,ByteSize offset,AsmOffset mode=basic_offset)93 Address(Register rn, ByteSize offset, AsmOffset mode = basic_offset) { 94 _base = rn; 95 _index = noreg; 96 _disp = in_bytes(offset); 97 _mode = mode; 98 _shift_imm = 0; 99 _shift = lsl; 100 _offset_op = add_offset; 101 } 102 #endif 103 Address(Register rn,Register rm,AsmShift shift=lsl,int shift_imm=0,AsmOffset mode=basic_offset,AsmOffsetOp offset_op=add_offset)104 Address(Register rn, Register rm, AsmShift shift = lsl, 105 int shift_imm = 0, AsmOffset mode = basic_offset, 106 AsmOffsetOp offset_op = add_offset) { 107 _base = rn; 108 _index = rm; 109 _disp = 0; 110 _shift = shift; 111 _shift_imm = shift_imm; 112 _mode = mode; 113 _offset_op = offset_op; 114 } 115 Address(Register rn,RegisterOrConstant offset,AsmShift shift=lsl,int shift_imm=0)116 Address(Register rn, RegisterOrConstant offset, AsmShift shift = lsl, 117 int shift_imm = 0) { 118 _base = rn; 119 if (offset.is_constant()) { 120 _index = noreg; 121 { 122 int off = (int) offset.as_constant(); 123 if (shift_imm != 0) { 124 assert(shift == lsl,"shift not yet encoded"); 125 off = off << shift_imm; 126 } 127 _disp = off; 128 } 129 _shift = lsl; 130 _shift_imm = 0; 131 } else { 132 _index = offset.as_register(); 133 _disp = 0; 134 _shift = shift; 135 _shift_imm = shift_imm; 136 } 137 _mode = basic_offset; 138 _offset_op = add_offset; 139 } 140 141 // [base + index * wordSize] indexed_ptr(Register base,Register index)142 static Address indexed_ptr(Register base, Register index) { 143 return Address(base, index, LSL, LogBytesPerWord); 144 } 145 146 // [base + index * BytesPerInt] indexed_32(Register base,Register index)147 static Address indexed_32(Register base, Register index) { 148 return Address(base, index, LSL, LogBytesPerInt); 149 } 150 151 // [base + index * BytesPerHeapOop] indexed_oop(Register base,Register index)152 static Address indexed_oop(Register base, Register index) { 153 return Address(base, index, LSL, LogBytesPerHeapOop); 154 } 155 plus_disp(int disp) const156 Address plus_disp(int disp) const { 157 assert((disp == 0) || (_index == noreg),"can't apply an offset to a register indexed address"); 158 Address a = (*this); 159 a._disp += disp; 160 return a; 161 } 162 rebase(Register new_base) const163 Address rebase(Register new_base) const { 164 Address a = (*this); 165 a._base = new_base; 166 return a; 167 } 168 encoding2() const169 int encoding2() const { 170 assert(_mode == basic_offset || _base != PC, "unpredictable instruction"); 171 if (_index == noreg) { 172 assert(-4096 < _disp && _disp < 4096, "encoding constraint"); 173 return _mode | up(_disp) << 23 | _base->encoding() << 16 | abs(_disp); 174 } else { 175 assert(_index != PC && (_mode == basic_offset || _index != _base), "unpredictable instruction"); 176 assert(_disp == 0 && (_shift_imm >> 5) == 0, "encoding constraint"); 177 return 1 << 25 | _offset_op << 23 | _mode | _base->encoding() << 16 | 178 _shift_imm << 7 | _shift << 5 | _index->encoding(); 179 } 180 } 181 encoding3() const182 int encoding3() const { 183 assert(_mode == basic_offset || _base != PC, "unpredictable instruction"); 184 if (_index == noreg) { 185 assert(-256 < _disp && _disp < 256, "encoding constraint"); 186 return _mode | up(_disp) << 23 | 1 << 22 | _base->encoding() << 16 | 187 (abs(_disp) & 0xf0) << 4 | abs(_disp) & 0x0f; 188 } else { 189 assert(_index != PC && (_mode == basic_offset || _index != _base), "unpredictable instruction"); 190 assert(_disp == 0 && _shift == lsl && _shift_imm == 0, "encoding constraint"); 191 return _mode | _offset_op << 23 | _base->encoding() << 16 | _index->encoding(); 192 } 193 } 194 encoding_ex() const195 int encoding_ex() const { 196 assert(_index == noreg && _disp == 0 && _mode == basic_offset && 197 _base != PC, "encoding constraint"); 198 return _base->encoding() << 16; 199 } 200 encoding_vfp() const201 int encoding_vfp() const { 202 assert(_index == noreg && _mode == basic_offset, "encoding constraint"); 203 assert(-1024 < _disp && _disp < 1024 && (_disp & 3) == 0, "encoding constraint"); 204 return _base->encoding() << 16 | up(_disp) << 23 | abs(_disp) >> 2; 205 } 206 encoding_simd() const207 int encoding_simd() const { 208 assert(_base != PC, "encoding constraint"); 209 assert(_index != PC && _index != SP, "encoding constraint"); 210 assert(_disp == 0, "encoding constraint"); 211 assert(_shift == 0, "encoding constraint"); 212 assert(_index == noreg || _mode == basic_offset, "encoding constraint"); 213 assert(_mode == basic_offset || _mode == post_indexed, "encoding constraint"); 214 int index; 215 if (_index == noreg) { 216 if (_mode == post_indexed) 217 index = 13; 218 else 219 index = 15; 220 } else { 221 index = _index->encoding(); 222 } 223 224 return _base->encoding() << 16 | index; 225 } 226 base() const227 Register base() const { 228 return _base; 229 } 230 index() const231 Register index() const { 232 return _index; 233 } 234 disp() const235 int disp() const { 236 return _disp; 237 } 238 mode() const239 AsmOffset mode() const { 240 return _mode; 241 } 242 shift_imm() const243 int shift_imm() const { 244 return _shift_imm; 245 } 246 shift() const247 AsmShift shift() const { 248 return _shift; 249 } 250 offset_op() const251 AsmOffsetOp offset_op() const { 252 return _offset_op; 253 } 254 uses(Register reg) const255 bool uses(Register reg) const { return _base == reg || _index == reg; } 256 rtype()257 const relocInfo::relocType rtype() { return _rspec.type(); } rspec()258 const RelocationHolder& rspec() { return _rspec; } 259 260 // Convert the raw encoding form into the form expected by the 261 // constructor for Address. 262 static Address make_raw(int base, int index, int scale, int disp, relocInfo::relocType disp_reloc); 263 }; 264 265 #ifdef COMPILER2 266 class VFP { 267 // Helper classes to detect whether a floating point constant can be 268 // encoded in a fconstd or fconsts instruction 269 // The conversion from the imm8, 8 bit constant, to the floating 270 // point value encoding is done with either: 271 // for single precision: imm8<7>:NOT(imm8<6>):Replicate(imm8<6>,5):imm8<5:0>:Zeros(19) 272 // or 273 // for double precision: imm8<7>:NOT(imm8<6>):Replicate(imm8<6>,8):imm8<5:0>:Zeros(48) 274 275 private: 276 class fpnum { 277 public: 278 virtual unsigned int f_hi4() const = 0; 279 virtual bool f_lo_is_null() const = 0; 280 virtual int e() const = 0; 281 virtual unsigned int s() const = 0; 282 can_be_imm8() const283 inline bool can_be_imm8() const { return e() >= -3 && e() <= 4 && f_lo_is_null(); } imm8() const284 inline unsigned char imm8() const { int v = (s() << 7) | (((e() - 1) & 0x7) << 4) | f_hi4(); assert((v >> 8) == 0, "overflow"); return v; } 285 }; 286 287 public: 288 class float_num : public fpnum { 289 public: float_num(float v)290 float_num(float v) { 291 _num.val = v; 292 } 293 f_hi4() const294 virtual unsigned int f_hi4() const { return (_num.bits << 9) >> (19+9); } f_lo_is_null() const295 virtual bool f_lo_is_null() const { return (_num.bits & ((1 << 19) - 1)) == 0; } e() const296 virtual int e() const { return ((_num.bits << 1) >> (23+1)) - 127; } s() const297 virtual unsigned int s() const { return _num.bits >> 31; } 298 299 private: 300 union { 301 float val; 302 unsigned int bits; 303 } _num; 304 }; 305 306 class double_num : public fpnum { 307 public: double_num(double v)308 double_num(double v) { 309 _num.val = v; 310 } 311 f_hi4() const312 virtual unsigned int f_hi4() const { return (_num.bits << 12) >> (48+12); } f_lo_is_null() const313 virtual bool f_lo_is_null() const { return (_num.bits & ((1LL << 48) - 1)) == 0; } e() const314 virtual int e() const { return ((_num.bits << 1) >> (52+1)) - 1023; } s() const315 virtual unsigned int s() const { return _num.bits >> 63; } 316 317 private: 318 union { 319 double val; 320 unsigned long long bits; 321 } _num; 322 }; 323 }; 324 #endif 325 326 #include "assembler_arm_32.hpp" 327 328 329 #endif // CPU_ARM_VM_ASSEMBLER_ARM_HPP 330