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 #ifdef AARCH64 44 enum AsmExtendOp { 45 ex_uxtb, ex_uxth, ex_uxtw, ex_uxtx, 46 ex_sxtb, ex_sxth, ex_sxtw, ex_sxtx, 47 48 ex_lsl = ex_uxtx 49 }; 50 #endif 51 52 enum AsmOffset { 53 #ifdef AARCH64 54 basic_offset = 0b00, 55 pre_indexed = 0b11, 56 post_indexed = 0b01 57 #else 58 basic_offset = 1 << 24, 59 pre_indexed = 1 << 24 | 1 << 21, 60 post_indexed = 0 61 #endif 62 }; 63 64 65 #ifndef AARCH64 66 enum AsmWriteback { 67 no_writeback, 68 writeback 69 }; 70 71 enum AsmOffsetOp { 72 sub_offset = 0, 73 add_offset = 1 74 }; 75 #endif 76 77 78 // ARM Addressing Modes 2 and 3 - Load and store 79 class Address { 80 private: 81 Register _base; 82 Register _index; 83 int _disp; 84 AsmOffset _mode; 85 RelocationHolder _rspec; 86 int _shift_imm; 87 #ifdef AARCH64 88 AsmExtendOp _extend; 89 #else 90 AsmShift _shift; 91 AsmOffsetOp _offset_op; 92 93 static inline int abs(int x) { return x < 0 ? -x : x; } 94 static inline int up (int x) { return x < 0 ? 0 : 1; } 95 #endif 96 97 #ifdef AARCH64 98 static const AsmExtendOp LSL = ex_lsl; 99 #else 100 static const AsmShift LSL = lsl; 101 #endif 102 103 public: 104 Address() : _base(noreg) {} 105 106 Address(Register rn, int offset = 0, AsmOffset mode = basic_offset) { 107 _base = rn; 108 _index = noreg; 109 _disp = offset; 110 _mode = mode; 111 _shift_imm = 0; 112 #ifdef AARCH64 113 _extend = ex_lsl; 114 #else 115 _shift = lsl; 116 _offset_op = add_offset; 117 #endif 118 } 119 120 #ifdef ASSERT 121 Address(Register rn, ByteSize offset, AsmOffset mode = basic_offset) { 122 _base = rn; 123 _index = noreg; 124 _disp = in_bytes(offset); 125 _mode = mode; 126 _shift_imm = 0; 127 #ifdef AARCH64 128 _extend = ex_lsl; 129 #else 130 _shift = lsl; 131 _offset_op = add_offset; 132 #endif 133 } 134 #endif 135 136 #ifdef AARCH64 137 Address(Register rn, Register rm, AsmExtendOp extend = ex_lsl, int shift_imm = 0) { 138 assert ((extend == ex_uxtw) || (extend == ex_lsl) || (extend == ex_sxtw) || (extend == ex_sxtx), "invalid extend for address mode"); 139 assert ((0 <= shift_imm) && (shift_imm <= 4), "shift amount is out of range"); 140 _base = rn; 141 _index = rm; 142 _disp = 0; 143 _mode = basic_offset; 144 _extend = extend; 145 _shift_imm = shift_imm; 146 } 147 #else 148 Address(Register rn, Register rm, AsmShift shift = lsl, 149 int shift_imm = 0, AsmOffset mode = basic_offset, 150 AsmOffsetOp offset_op = add_offset) { 151 _base = rn; 152 _index = rm; 153 _disp = 0; 154 _shift = shift; 155 _shift_imm = shift_imm; 156 _mode = mode; 157 _offset_op = offset_op; 158 } 159 160 Address(Register rn, RegisterOrConstant offset, AsmShift shift = lsl, 161 int shift_imm = 0) { 162 _base = rn; 163 if (offset.is_constant()) { 164 _index = noreg; 165 { 166 int off = (int) offset.as_constant(); 167 if (shift_imm != 0) { 168 assert(shift == lsl,"shift not yet encoded"); 169 off = off << shift_imm; 170 } 171 _disp = off; 172 } 173 _shift = lsl; 174 _shift_imm = 0; 175 } else { 176 _index = offset.as_register(); 177 _disp = 0; 178 _shift = shift; 179 _shift_imm = shift_imm; 180 } 181 _mode = basic_offset; 182 _offset_op = add_offset; 183 } 184 #endif // AARCH64 185 186 // [base + index * wordSize] 187 static Address indexed_ptr(Register base, Register index) { 188 return Address(base, index, LSL, LogBytesPerWord); 189 } 190 191 // [base + index * BytesPerInt] 192 static Address indexed_32(Register base, Register index) { 193 return Address(base, index, LSL, LogBytesPerInt); 194 } 195 196 // [base + index * BytesPerHeapOop] 197 static Address indexed_oop(Register base, Register index) { 198 return Address(base, index, LSL, LogBytesPerHeapOop); 199 } 200 201 Address plus_disp(int disp) const { 202 assert((disp == 0) || (_index == noreg),"can't apply an offset to a register indexed address"); 203 Address a = (*this); 204 a._disp += disp; 205 return a; 206 } 207 208 Address rebase(Register new_base) const { 209 Address a = (*this); 210 a._base = new_base; 211 return a; 212 } 213 214 #ifdef AARCH64 215 int encoding_simd() const { 216 assert(_index != SP, "encoding constraint"); 217 assert(_disp == 0 || _mode == post_indexed, "encoding constraint"); 218 assert(_index == noreg || _mode == basic_offset, "encoding constraint"); 219 assert(_mode == basic_offset || _mode == post_indexed, "encoding constraint"); 220 assert(_extend == ex_lsl, "encoding constraint"); 221 int index; 222 if (_index == noreg) { 223 if (_mode == post_indexed) 224 index = 0b100 << 5 | 31; 225 else 226 index = 0; 227 } else { 228 index = 0b100 << 5 | _index->encoding(); 229 } 230 return index << 16 | _base->encoding_with_sp() << 5; 231 } 232 #else /* !AARCH64 */ 233 int encoding2() const { 234 assert(_mode == basic_offset || _base != PC, "unpredictable instruction"); 235 if (_index == noreg) { 236 assert(-4096 < _disp && _disp < 4096, "encoding constraint"); 237 return _mode | up(_disp) << 23 | _base->encoding() << 16 | abs(_disp); 238 } else { 239 assert(_index != PC && (_mode == basic_offset || _index != _base), "unpredictable instruction"); 240 assert(_disp == 0 && (_shift_imm >> 5) == 0, "encoding constraint"); 241 return 1 << 25 | _offset_op << 23 | _mode | _base->encoding() << 16 | 242 _shift_imm << 7 | _shift << 5 | _index->encoding(); 243 } 244 } 245 246 int encoding3() const { 247 assert(_mode == basic_offset || _base != PC, "unpredictable instruction"); 248 if (_index == noreg) { 249 assert(-256 < _disp && _disp < 256, "encoding constraint"); 250 return _mode | up(_disp) << 23 | 1 << 22 | _base->encoding() << 16 | 251 (abs(_disp) & 0xf0) << 4 | abs(_disp) & 0x0f; 252 } else { 270 271 int encoding_simd() const { 272 assert(_base != PC, "encoding constraint"); 273 assert(_index != PC && _index != SP, "encoding constraint"); 274 assert(_disp == 0, "encoding constraint"); 275 assert(_shift == 0, "encoding constraint"); 276 assert(_index == noreg || _mode == basic_offset, "encoding constraint"); 277 assert(_mode == basic_offset || _mode == post_indexed, "encoding constraint"); 278 int index; 279 if (_index == noreg) { 280 if (_mode == post_indexed) 281 index = 13; 282 else 283 index = 15; 284 } else { 285 index = _index->encoding(); 286 } 287 288 return _base->encoding() << 16 | index; 289 } 290 #endif // !AARCH64 291 292 Register base() const { 293 return _base; 294 } 295 296 Register index() const { 297 return _index; 298 } 299 300 int disp() const { 301 return _disp; 302 } 303 304 AsmOffset mode() const { 305 return _mode; 306 } 307 308 int shift_imm() const { 309 return _shift_imm; 310 } 311 312 #ifdef AARCH64 313 AsmExtendOp extend() const { 314 return _extend; 315 } 316 #else 317 AsmShift shift() const { 318 return _shift; 319 } 320 321 AsmOffsetOp offset_op() const { 322 return _offset_op; 323 } 324 #endif 325 326 bool uses(Register reg) const { return _base == reg || _index == reg; } 327 328 const relocInfo::relocType rtype() { return _rspec.type(); } 329 const RelocationHolder& rspec() { return _rspec; } 330 331 // Convert the raw encoding form into the form expected by the 332 // constructor for Address. 333 static Address make_raw(int base, int index, int scale, int disp, relocInfo::relocType disp_reloc); 334 }; 335 336 #ifdef COMPILER2 337 class VFP { 338 // Helper classes to detect whether a floating point constant can be 339 // encoded in a fconstd or fconsts instruction 340 // The conversion from the imm8, 8 bit constant, to the floating 341 // point value encoding is done with either: 342 // for single precision: imm8<7>:NOT(imm8<6>):Replicate(imm8<6>,5):imm8<5:0>:Zeros(19) 343 // or 344 // for double precision: imm8<7>:NOT(imm8<6>):Replicate(imm8<6>,8):imm8<5:0>:Zeros(48) 377 class double_num : public fpnum { 378 public: 379 double_num(double v) { 380 _num.val = v; 381 } 382 383 virtual unsigned int f_hi4() const { return (_num.bits << 12) >> (48+12); } 384 virtual bool f_lo_is_null() const { return (_num.bits & ((1LL << 48) - 1)) == 0; } 385 virtual int e() const { return ((_num.bits << 1) >> (52+1)) - 1023; } 386 virtual unsigned int s() const { return _num.bits >> 63; } 387 388 private: 389 union { 390 double val; 391 unsigned long long bits; 392 } _num; 393 }; 394 }; 395 #endif 396 397 #ifdef AARCH64 398 #include "assembler_arm_64.hpp" 399 #else 400 #include "assembler_arm_32.hpp" 401 #endif 402 403 404 #endif // CPU_ARM_VM_ASSEMBLER_ARM_HPP | 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 74 static inline int abs(int x) { return x < 0 ? -x : x; } 75 static inline int up (int x) { return x < 0 ? 0 : 1; } 76 77 static const AsmShift LSL = lsl; 78 79 public: 80 Address() : _base(noreg) {} 81 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 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 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 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] 142 static Address indexed_ptr(Register base, Register index) { 143 return Address(base, index, LSL, LogBytesPerWord); 144 } 145 146 // [base + index * BytesPerInt] 147 static Address indexed_32(Register base, Register index) { 148 return Address(base, index, LSL, LogBytesPerInt); 149 } 150 151 // [base + index * BytesPerHeapOop] 152 static Address indexed_oop(Register base, Register index) { 153 return Address(base, index, LSL, LogBytesPerHeapOop); 154 } 155 156 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 163 Address rebase(Register new_base) const { 164 Address a = (*this); 165 a._base = new_base; 166 return a; 167 } 168 169 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 182 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 { 206 207 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 227 Register base() const { 228 return _base; 229 } 230 231 Register index() const { 232 return _index; 233 } 234 235 int disp() const { 236 return _disp; 237 } 238 239 AsmOffset mode() const { 240 return _mode; 241 } 242 243 int shift_imm() const { 244 return _shift_imm; 245 } 246 247 AsmShift shift() const { 248 return _shift; 249 } 250 251 AsmOffsetOp offset_op() const { 252 return _offset_op; 253 } 254 255 bool uses(Register reg) const { return _base == reg || _index == reg; } 256 257 const relocInfo::relocType rtype() { return _rspec.type(); } 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) 306 class double_num : public fpnum { 307 public: 308 double_num(double v) { 309 _num.val = v; 310 } 311 312 virtual unsigned int f_hi4() const { return (_num.bits << 12) >> (48+12); } 313 virtual bool f_lo_is_null() const { return (_num.bits & ((1LL << 48) - 1)) == 0; } 314 virtual int e() const { return ((_num.bits << 1) >> (52+1)) - 1023; } 315 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 |