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_32_HPP 26 #define CPU_ARM_VM_ASSEMBLER_ARM_32_HPP 27 28 // ARM Addressing Mode 1 - Data processing operands 29 class AsmOperand { 30 private: 31 int _encoding; 32 33 void initialize_rotated_imm(unsigned int imm); 34 35 void encode(int imm_8) { 36 if ((imm_8 >> 8) == 0) { 37 _encoding = 1 << 25 | imm_8; // the most common case 38 } else { 39 initialize_rotated_imm((unsigned int)imm_8); // slow case 40 } 41 } 42 43 void encode(Register rm, AsmShift shift, int shift_imm) { 44 assert((shift_imm >> 5) == 0, "encoding constraint"); 45 _encoding = shift_imm << 7 | shift << 5 | rm->encoding(); 46 } 47 48 public: 49 50 AsmOperand(Register reg) { 51 _encoding = reg->encoding(); 52 } 53 54 AsmOperand(int imm_8) { 55 encode(imm_8); 56 } 57 58 #ifdef ASSERT 59 AsmOperand(ByteSize bytesize_8) { 60 const int imm_8 = in_bytes(bytesize_8); 61 encode(imm_8); 62 } 63 #endif // ASSERT 64 65 AsmOperand(Register rm, AsmShift shift, int shift_imm) { 66 encode(rm,shift,shift_imm); 67 } 68 69 AsmOperand(Register rm, AsmShift shift, Register rs) { 70 assert(rm != PC && rs != PC, "unpredictable instruction"); 71 _encoding = rs->encoding() << 8 | shift << 5 | 1 << 4 | rm->encoding(); 72 } 73 74 AsmOperand(RegisterOrConstant offset, AsmShift shift = lsl, int shift_imm = 0) { 75 if (offset.is_register()) { 76 encode(offset.as_register(), shift, shift_imm); 77 } else { 78 assert(shift == lsl,"shift type not yet encoded"); 79 int imm_8 = ((int)offset.as_constant()) << shift_imm; 80 encode(imm_8); 81 } 82 } 83 84 int encoding() const { 85 return _encoding; 86 } 87 88 bool is_immediate() const { 89 return _encoding & (1 << 25) ? true : false; 90 } 91 92 Register base_register() const { 93 assert(!is_immediate(), "is_immediate, no base reg"); 94 return as_Register(_encoding & 15); 95 } 96 97 static bool is_rotated_imm(unsigned int imm); 98 }; 99 100 101 // ARM Addressing Mode 4 - Load and store multiple 102 class RegisterSet { 103 private: 104 int _encoding; 105 106 RegisterSet(int encoding) { 107 _encoding = encoding; 108 } 109 110 public: 111 112 RegisterSet(Register reg) { 113 _encoding = 1 << reg->encoding(); 114 } 115 116 RegisterSet() { 117 _encoding = 0; 118 } 119 120 RegisterSet(Register first, Register last) { 121 assert(first < last, "encoding constraint"); 122 _encoding = (1 << (last->encoding() + 1)) - (1 << first->encoding()); 123 } 124 125 friend RegisterSet operator | (const RegisterSet set1, const RegisterSet set2) { 126 assert((set1._encoding & set2._encoding) == 0, 127 "encoding constraint"); 128 return RegisterSet(set1._encoding | set2._encoding); 129 } 130 131 int encoding() const { 132 return _encoding; 133 } 134 135 bool contains(Register reg) const { 136 return (_encoding & (1 << reg->encoding())) != 0; 137 } 138 139 // number of registers in the set 140 int size() const { 141 int count = 0; 142 unsigned int remaining = (unsigned int) _encoding; 143 while (remaining != 0) { 144 if ((remaining & 1) != 0) count++; 145 remaining >>= 1; 146 } 147 return count; 148 } 149 }; 150 151 #if R9_IS_SCRATCHED 152 #define R9ifScratched RegisterSet(R9) 153 #else 154 #define R9ifScratched RegisterSet() 155 #endif 156 157 // ARM Addressing Mode 5 - Load and store multiple VFP registers 158 class FloatRegisterSet { 159 private: 160 int _encoding; 161 162 public: 163 164 FloatRegisterSet(FloatRegister reg) { 165 if (reg->hi_bit() == 0) { 166 _encoding = reg->hi_bits() << 12 | reg->lo_bit() << 22 | 1; 167 } else { 168 assert (reg->lo_bit() == 0, "impossible encoding"); 169 _encoding = reg->hi_bits() << 12 | reg->hi_bit() << 22 | 1; 170 } 171 } 172 173 FloatRegisterSet(FloatRegister first, int count) { 174 assert(count >= 1, "encoding constraint"); 175 if (first->hi_bit() == 0) { 176 _encoding = first->hi_bits() << 12 | first->lo_bit() << 22 | count; 177 } else { 178 assert (first->lo_bit() == 0, "impossible encoding"); 179 _encoding = first->hi_bits() << 12 | first->hi_bit() << 22 | count; 180 } 181 } 182 183 int encoding_s() const { 184 return _encoding; 185 } 186 187 int encoding_d() const { 188 assert((_encoding & 0xFF) <= 16, "no more than 16 double registers" ); 189 return (_encoding & 0xFFFFFF00) | ((_encoding & 0xFF) << 1); 190 } 191 192 }; 193 194 195 class Assembler : public AbstractAssembler { 196 197 public: 198 199 static const int LogInstructionSize = 2; 200 static const int InstructionSize = 1 << LogInstructionSize; 201 202 static inline AsmCondition inverse(AsmCondition cond) { 203 assert ((cond != al) && (cond != nv), "AL and NV conditions cannot be inversed"); 204 return (AsmCondition)((int)cond ^ 1); 205 } 206 207 // Returns true if given value can be used as immediate in arithmetic (add/sub/cmp/cmn) instructions. 208 static inline bool is_arith_imm_in_range(intx value) { 209 return AsmOperand::is_rotated_imm(value); 210 } 211 212 // Arithmetic instructions 213 214 #define F(mnemonic, opcode) \ 215 void mnemonic(Register rd, Register rn, AsmOperand operand, AsmCondition cond = al) { \ 216 emit_int32(cond << 28 | opcode << 21 | rn->encoding() << 16 | \ 217 rd->encoding() << 12 | operand.encoding()); \ 218 } \ 219 void mnemonic##s(Register rd, Register rn, AsmOperand operand, AsmCondition cond = al) { \ 220 emit_int32(cond << 28 | opcode << 21 | 1 << 20 | rn->encoding() << 16 | \ 221 rd->encoding() << 12 | operand.encoding()); \ 222 } 223 224 F(andr, 0) 225 F(eor, 1) 226 F(sub, 2) 227 F(rsb, 3) 228 F(add, 4) 229 F(adc, 5) 230 F(sbc, 6) 231 F(rsc, 7) 232 F(orr, 12) 233 F(bic, 14) 234 #undef F 235 236 #define F(mnemonic, opcode) \ 237 void mnemonic(Register rn, AsmOperand operand, AsmCondition cond = al) { \ 238 emit_int32(cond << 28 | opcode << 21 | 1 << 20 | rn->encoding() << 16 | \ 239 operand.encoding()); \ 240 } 241 242 F(tst, 8) 243 F(teq, 9) 244 F(cmp, 10) 245 F(cmn, 11) 246 #undef F 247 248 #define F(mnemonic, opcode) \ 249 void mnemonic(Register rd, AsmOperand operand, AsmCondition cond = al) { \ 250 emit_int32(cond << 28 | opcode << 21 | rd->encoding() << 12 | \ 251 operand.encoding()); \ 252 } \ 253 void mnemonic##s(Register rd, AsmOperand operand, AsmCondition cond = al) { \ 254 emit_int32(cond << 28 | opcode << 21 | 1 << 20 | rd->encoding() << 12 | \ 255 operand.encoding()); \ 256 } 257 258 F(mov, 13) 259 F(mvn, 15) 260 #undef F 261 262 void msr(uint fields, AsmOperand operand, AsmCondition cond = al) { 263 assert((operand.encoding() & (1<<25)) || ((operand.encoding() & 0xff0) == 0), "invalid addressing mode"); 264 emit_int32(cond << 28 | 1 << 24 | 1 << 21 | fields << 16 | 0xf << 12 | operand.encoding()); 265 } 266 267 void mrs(uint fields, Register Rd, AsmCondition cond = al) { 268 emit_int32(cond << 28 | 1 << 24 | (fields|0xf) << 16 | (Rd->encoding() << 12)); 269 } 270 271 272 enum { 273 CPSR = 0x00, CPSR_c = 0x01, CPSR_x = 0x02, CPSR_xc = 0x03, 274 CPSR_s = 0x004, CPSR_sc = 0x05, CPSR_sx = 0x06, CPSR_sxc = 0x07, 275 CPSR_f = 0x08, CPSR_fc = 0x09, CPSR_fx = 0x0a, CPSR_fxc = 0x0b, 276 CPSR_fs = 0x0c, CPSR_fsc = 0x0d, CPSR_fsx = 0x0e, CPSR_fsxc = 0x0f, 277 SPSR = 0x40, SPSR_c = 0x41, SPSR_x = 0x42, SPSR_xc = 0x43, 278 SPSR_s = 0x44, SPSR_sc = 0x45, SPSR_sx = 0x46, SPSR_sxc = 0x47, 279 SPSR_f = 0x48, SPSR_fc = 0x49, SPSR_fx = 0x4a, SPSR_fxc = 0x4b, 280 SPSR_fs = 0x4c, SPSR_fsc = 0x4d, SPSR_fsx = 0x4e, SPSR_fsxc = 0x4f 281 }; 282 283 #define F(mnemonic, opcode) \ 284 void mnemonic(Register rdlo, Register rdhi, Register rm, Register rs, \ 285 AsmCondition cond = al) { \ 286 emit_int32(cond << 28 | opcode << 21 | rdhi->encoding() << 16 | \ 287 rdlo->encoding() << 12 | rs->encoding() << 8 | 0x9 << 4 | rm->encoding()); \ 288 } \ 289 void mnemonic##s(Register rdlo, Register rdhi, Register rm, Register rs, \ 290 AsmCondition cond = al) { \ 291 emit_int32(cond << 28 | opcode << 21 | 1 << 20 | rdhi->encoding() << 16 | \ 292 rdlo->encoding() << 12 | rs->encoding() << 8 | 0x9 << 4 | rm->encoding()); \ 293 } 294 295 F(umull, 4) 296 F(umlal, 5) 297 F(smull, 6) 298 F(smlal, 7) 299 #undef F 300 301 void mul(Register rd, Register rm, Register rs, AsmCondition cond = al) { 302 emit_int32(cond << 28 | rd->encoding() << 16 | 303 rs->encoding() << 8 | 0x9 << 4 | rm->encoding()); 304 } 305 306 void muls(Register rd, Register rm, Register rs, AsmCondition cond = al) { 307 emit_int32(cond << 28 | 1 << 20 | rd->encoding() << 16 | 308 rs->encoding() << 8 | 0x9 << 4 | rm->encoding()); 309 } 310 311 void mla(Register rd, Register rm, Register rs, Register rn, AsmCondition cond = al) { 312 emit_int32(cond << 28 | 1 << 21 | rd->encoding() << 16 | 313 rn->encoding() << 12 | rs->encoding() << 8 | 0x9 << 4 | rm->encoding()); 314 } 315 316 void mlas(Register rd, Register rm, Register rs, Register rn, AsmCondition cond = al) { 317 emit_int32(cond << 28 | 1 << 21 | 1 << 20 | rd->encoding() << 16 | 318 rn->encoding() << 12 | rs->encoding() << 8 | 0x9 << 4 | rm->encoding()); 319 } 320 321 // Loads and stores 322 323 #define F(mnemonic, l, b) \ 324 void mnemonic(Register rd, Address addr, AsmCondition cond = al) { \ 325 emit_int32(cond << 28 | 1 << 26 | b << 22 | l << 20 | \ 326 rd->encoding() << 12 | addr.encoding2()); \ 327 } 328 329 F(ldr, 1, 0) 330 F(ldrb, 1, 1) 331 F(str, 0, 0) 332 F(strb, 0, 1) 333 #undef F 334 335 #undef F 336 337 #define F(mnemonic, l, sh, even) \ 338 void mnemonic(Register rd, Address addr, AsmCondition cond = al) { \ 339 assert(!even || (rd->encoding() & 1) == 0, "must be even"); \ 340 emit_int32(cond << 28 | l << 20 | rd->encoding() << 12 | \ 341 1 << 7 | sh << 5 | 1 << 4 | addr.encoding3()); \ 342 } 343 344 F(strh, 0, 1, false) 345 F(ldrh, 1, 1, false) 346 F(ldrsb, 1, 2, false) 347 F(ldrsh, 1, 3, false) 348 F(strd, 0, 3, true) 349 350 #undef F 351 352 void ldrd(Register rd, Address addr, AsmCondition cond = al) { 353 assert((rd->encoding() & 1) == 0, "must be even"); 354 assert(!addr.index()->is_valid() || 355 (addr.index()->encoding() != rd->encoding() && 356 addr.index()->encoding() != (rd->encoding()+1)), "encoding constraint"); 357 emit_int32(cond << 28 | rd->encoding() << 12 | 0xD /* 0b1101 */ << 4 | addr.encoding3()); 358 } 359 360 #define F(mnemonic, l, pu) \ 361 void mnemonic(Register rn, RegisterSet reg_set, \ 362 AsmWriteback w = no_writeback, AsmCondition cond = al) { \ 363 assert(reg_set.encoding() != 0 && (w == no_writeback || \ 364 (reg_set.encoding() & (1 << rn->encoding())) == 0), \ 365 "unpredictable instruction"); \ 366 emit_int32(cond << 28 | 4 << 25 | pu << 23 | w << 21 | l << 20 | \ 367 rn->encoding() << 16 | reg_set.encoding()); \ 368 } 369 370 F(ldmda, 1, 0) F(ldmfa, 1, 0) 371 F(ldmia, 1, 1) F(ldmfd, 1, 1) 372 F(ldmdb, 1, 2) F(ldmea, 1, 2) 373 F(ldmib, 1, 3) F(ldmed, 1, 3) 374 F(stmda, 0, 0) F(stmed, 0, 0) 375 F(stmia, 0, 1) F(stmea, 0, 1) 376 F(stmdb, 0, 2) F(stmfd, 0, 2) 377 F(stmib, 0, 3) F(stmfa, 0, 3) 378 #undef F 379 380 void ldrex(Register rd, Address addr, AsmCondition cond = al) { 381 assert(rd != PC, "unpredictable instruction"); 382 emit_int32(cond << 28 | 0x19 << 20 | addr.encoding_ex() | 383 rd->encoding() << 12 | 0xf9f); 384 } 385 386 void strex(Register rs, Register rd, Address addr, AsmCondition cond = al) { 387 assert(rd != PC && rs != PC && 388 rs != rd && rs != addr.base(), "unpredictable instruction"); 389 emit_int32(cond << 28 | 0x18 << 20 | addr.encoding_ex() | 390 rs->encoding() << 12 | 0xf90 | rd->encoding()); 391 } 392 393 void ldrexd(Register rd, Address addr, AsmCondition cond = al) { 394 assert(rd != PC, "unpredictable instruction"); 395 emit_int32(cond << 28 | 0x1B << 20 | addr.encoding_ex() | 396 rd->encoding() << 12 | 0xf9f); 397 } 398 399 void strexd(Register rs, Register rd, Address addr, AsmCondition cond = al) { 400 assert(rd != PC && rs != PC && 401 rs != rd && rs != addr.base(), "unpredictable instruction"); 402 emit_int32(cond << 28 | 0x1A << 20 | addr.encoding_ex() | 403 rs->encoding() << 12 | 0xf90 | rd->encoding()); 404 } 405 406 void clrex() { 407 emit_int32(0xF << 28 | 0x57 << 20 | 0xFF << 12 | 0x01f); 408 } 409 410 // Miscellaneous instructions 411 412 void clz(Register rd, Register rm, AsmCondition cond = al) { 413 emit_int32(cond << 28 | 0x016f0f10 | rd->encoding() << 12 | rm->encoding()); 414 } 415 416 void rev(Register rd, Register rm, AsmCondition cond = al) { 417 emit_int32(cond << 28 | 0x06bf0f30 | rd->encoding() << 12 | rm->encoding()); 418 } 419 420 void rev16(Register rd, Register rm, AsmCondition cond = al) { 421 emit_int32(cond << 28 | 0x6bf0fb0 | rd->encoding() << 12 | rm->encoding()); 422 } 423 424 void revsh(Register rd, Register rm, AsmCondition cond = al) { 425 emit_int32(cond << 28 | 0x6ff0fb0 | rd->encoding() << 12 | rm->encoding()); 426 } 427 428 void rbit(Register rd, Register rm, AsmCondition cond = al) { 429 emit_int32(cond << 28 | 0x6ff0f30 | rd->encoding() << 12 | rm->encoding()); 430 } 431 432 void pld(Address addr) { 433 emit_int32(0xf550f000 | addr.encoding2()); 434 } 435 436 void pldw(Address addr) { 437 assert(VM_Version::arm_arch() >= 7 && os::is_MP(), "no pldw on this processor"); 438 emit_int32(0xf510f000 | addr.encoding2()); 439 } 440 441 void svc(int imm_24, AsmCondition cond = al) { 442 assert((imm_24 >> 24) == 0, "encoding constraint"); 443 emit_int32(cond << 28 | 0xf << 24 | imm_24); 444 } 445 446 void ubfx(Register rd, Register rn, unsigned int lsb, unsigned int width, AsmCondition cond = al) { 447 assert(VM_Version::arm_arch() >= 7, "no ubfx on this processor"); 448 assert(width > 0, "must be"); 449 assert(lsb < 32, "must be"); 450 emit_int32(cond << 28 | 0x3f << 21 | (width - 1) << 16 | rd->encoding() << 12 | 451 lsb << 7 | 0x5 << 4 | rn->encoding()); 452 } 453 454 void uxtb(Register rd, Register rm, unsigned int rotation = 0, AsmCondition cond = al) { 455 assert(VM_Version::arm_arch() >= 7, "no uxtb on this processor"); 456 assert((rotation % 8) == 0 && (rotation <= 24), "encoding constraint"); 457 emit_int32(cond << 28 | 0x6e << 20 | 0xf << 16 | rd->encoding() << 12 | 458 (rotation >> 3) << 10 | 0x7 << 4 | rm->encoding()); 459 } 460 461 // ARM Memory Barriers 462 // 463 // There are two types of memory barriers defined for the ARM processor 464 // DataSynchronizationBarrier and DataMemoryBarrier 465 // 466 // The Linux kernel uses the DataMemoryBarrier for all of it's 467 // memory barrier operations (smp_mb, smp_rmb, smp_wmb) 468 // 469 // There are two forms of each barrier instruction. 470 // The mcr forms are supported on armv5 and newer architectures 471 // 472 // The dmb, dsb instructions were added in armv7 473 // architectures and are compatible with their mcr 474 // predecessors. 475 // 476 // Here are the encodings for future reference: 477 // 478 // DataSynchronizationBarrier (dsb) 479 // on ARMv7 - emit_int32(0xF57FF04F) 480 // 481 // on ARMv5+ - mcr p15, 0, Rtmp, c7, c10, 4 on earlier processors 482 // emit_int32(0xe << 28 | 0xe << 24 | 0x7 << 16 | Rtmp->encoding() << 12 | 483 // 0xf << 8 | 0x9 << 4 | 0xa); 484 // 485 // DataMemoryBarrier (dmb) 486 // on ARMv7 - emit_int32(0xF57FF05F) 487 // 488 // on ARMv5+ - mcr p15, 0, Rtmp, c7, c10, 5 on earlier processors 489 // emit_int32(0xe << 28 | 0xe << 24 | 0x7 << 16 | Rtmp->encoding() << 12 | 490 // 0xf << 8 | 0xb << 4 | 0xa); 491 // 492 493 enum DMB_Opt { 494 DMB_all = 0xf, 495 DMB_st = 0xe, 496 }; 497 498 void dmb(DMB_Opt opt, Register reg) { 499 if (VM_Version::arm_arch() >= 7) { 500 emit_int32(0xF57FF050 | opt); 501 } else if (VM_Version::arm_arch() == 6) { 502 bool preserve_tmp = (reg == noreg); 503 if(preserve_tmp) { 504 reg = Rtemp; 505 str(reg, Address(SP, -wordSize, pre_indexed)); 506 } 507 mov(reg, 0); 508 // DataMemoryBarrier 509 emit_int32(0xe << 28 | 510 0xe << 24 | 511 0x7 << 16 | 512 reg->encoding() << 12 | 513 0xf << 8 | 514 0xb << 4 | 515 0xa); 516 if(preserve_tmp) { 517 ldr(reg, Address(SP, wordSize, post_indexed)); 518 } 519 } 520 } 521 522 void dsb(Register reg) { 523 if (VM_Version::arm_arch() >= 7) { 524 emit_int32(0xF57FF04F); 525 } else { 526 bool preserve_tmp = (reg == noreg); 527 if(preserve_tmp) { 528 reg = Rtemp; 529 str(reg, Address(SP, -wordSize, pre_indexed)); 530 } 531 mov(reg, 0); 532 // DataSynchronizationBarrier 533 emit_int32(0xe << 28 | 534 0xe << 24 | 535 0x7 << 16 | 536 reg->encoding() << 12 | 537 0xf << 8 | 538 0x9 << 4 | 539 0xa); 540 if(preserve_tmp) { 541 ldr(reg, Address(SP, wordSize, post_indexed)); 542 } 543 } 544 } 545 546 547 #define F(mnemonic, b) \ 548 void mnemonic(Register rd, Register rm, Register rn, AsmCondition cond = al) { \ 549 assert(rn != rm && rn != rd, "unpredictable instruction"); \ 550 emit_int32(cond << 28 | 0x2 << 23 | b << 22 | rn->encoding() << 16 | \ 551 rd->encoding() << 12 | 9 << 4 | rm->encoding()); \ 552 } 553 554 F(swp, 0) 555 F(swpb, 1) 556 #undef F 557 558 // Branches 559 560 #define F(mnemonic, l) \ 561 void mnemonic(Register rm, AsmCondition cond = al) { \ 562 emit_int32(cond << 28 | 0x012fff10 | l << 5 | rm->encoding()); \ 563 } 564 565 F(bx, 0) 566 F(blx, 1) 567 #undef F 568 569 #define F(mnemonic, l) \ 570 void mnemonic(address target, AsmCondition cond = al) { \ 571 unsigned int offset = (unsigned int)(target - pc() - 8); \ 572 assert((offset & 3) == 0, "bad alignment"); \ 573 assert((offset >> 25) == 0 || ((int)offset >> 25) == -1, "offset is too large"); \ 574 emit_int32(cond << 28 | l << 24 | offset << 6 >> 8); \ 575 } 576 577 F(b, 0xa) 578 F(bl, 0xb) 579 #undef F 580 581 void udf(int imm_16) { 582 assert((imm_16 >> 16) == 0, "encoding constraint"); 583 emit_int32(0xe7f000f0 | (imm_16 & 0xfff0) << 8 | (imm_16 & 0xf)); 584 } 585 586 // ARMv7 instructions 587 588 #define F(mnemonic, wt) \ 589 void mnemonic(Register rd, int imm_16, AsmCondition cond = al) { \ 590 assert((imm_16 >> 16) == 0, "encoding constraint"); \ 591 emit_int32(cond << 28 | wt << 20 | rd->encoding() << 12 | \ 592 (imm_16 & 0xf000) << 4 | (imm_16 & 0xfff)); \ 593 } 594 595 F(movw, 0x30) 596 F(movt, 0x34) 597 #undef F 598 599 // VFP Support 600 601 // Checks that VFP instructions are not used in SOFTFP mode. 602 #ifdef __SOFTFP__ 603 #define CHECK_VFP_PRESENT ShouldNotReachHere() 604 #else 605 #define CHECK_VFP_PRESENT 606 #endif // __SOFTFP__ 607 608 static const int single_cp_num = 0xa00; 609 static const int double_cp_num = 0xb00; 610 611 // Bits P, Q, R, S collectively form the opcode 612 #define F(mnemonic, P, Q, R, S) \ 613 void mnemonic##d(FloatRegister fd, FloatRegister fn, FloatRegister fm, \ 614 AsmCondition cond = al) { \ 615 CHECK_VFP_PRESENT; \ 616 assert(fn->lo_bit() == 0 && fd->lo_bit() == 0 && fm->lo_bit() == 0, "single precision register?"); \ 617 emit_int32(cond << 28 | 0x7 << 25 | double_cp_num | \ 618 P << 23 | Q << 21 | R << 20 | S << 6 | \ 619 fn->hi_bits() << 16 | fn->hi_bit() << 7 | \ 620 fd->hi_bits() << 12 | fd->hi_bit() << 22 | \ 621 fm->hi_bits() | fm->hi_bit() << 5); \ 622 } \ 623 void mnemonic##s(FloatRegister fd, FloatRegister fn, FloatRegister fm, \ 624 AsmCondition cond = al) { \ 625 assert(fn->hi_bit() == 0 && fd->hi_bit() == 0 && fm->hi_bit() == 0, "double precision register?"); \ 626 CHECK_VFP_PRESENT; \ 627 emit_int32(cond << 28 | 0x7 << 25 | single_cp_num | \ 628 P << 23 | Q << 21 | R << 20 | S << 6 | \ 629 fn->hi_bits() << 16 | fn->lo_bit() << 7 | \ 630 fd->hi_bits() << 12 | fd->lo_bit() << 22 | \ 631 fm->hi_bits() | fm->lo_bit() << 5); \ 632 } 633 634 F(fmac, 0, 0, 0, 0) // Fd = Fd + (Fn * Fm) 635 F(fnmac, 0, 0, 0, 1) // Fd = Fd - (Fn * Fm) 636 F(fmsc, 0, 0, 1, 0) // Fd = -Fd + (Fn * Fm) 637 F(fnmsc, 0, 0, 1, 1) // Fd = -Fd - (Fn * Fm) 638 639 F(fmul, 0, 1, 0, 0) // Fd = Fn * Fm 640 F(fnmul, 0, 1, 0, 1) // Fd = -(Fn * Fm) 641 F(fadd, 0, 1, 1, 0) // Fd = Fn + Fm 642 F(fsub, 0, 1, 1, 1) // Fd = Fn - Fm 643 F(fdiv, 1, 0, 0, 0) // Fd = Fn / Fm 644 #undef F 645 646 enum VElem_Size { 647 VELEM_SIZE_8 = 0x00, 648 VELEM_SIZE_16 = 0x01, 649 VELEM_SIZE_32 = 0x02, 650 VELEM_SIZE_64 = 0x03 651 }; 652 653 enum VLD_Type { 654 VLD1_TYPE_1_REG = 0x7 /* 0b0111 */, 655 VLD1_TYPE_2_REGS = 0xA /* 0b1010 */, 656 VLD1_TYPE_3_REGS = 0x6 /* 0b0110 */, 657 VLD1_TYPE_4_REGS = 0x2 /* 0b0010 */ 658 }; 659 660 enum VFloat_Arith_Size { 661 VFA_SIZE_F32 = 0x0 /* 0b0 */, 662 }; 663 664 // Bits P, Q, R, S collectively form the opcode 665 #define F(mnemonic, P, Q, R, S) \ 666 void mnemonic(FloatRegister fd, FloatRegister fn, FloatRegister fm, \ 667 int size, int quad) { \ 668 CHECK_VFP_PRESENT; \ 669 assert(VM_Version::has_simd(), "simd instruction"); \ 670 assert(fn->lo_bit() == 0 && fd->lo_bit() == 0 && fm->lo_bit() == 0, \ 671 "single precision register?"); \ 672 assert(!quad || ((fn->hi_bits() | fd->hi_bits() | fm->hi_bits()) & 1) == 0, \ 673 "quad precision register?"); \ 674 emit_int32(0xf << 28 | P << 23 | Q << 8 | R << 4 | \ 675 S << 21 | size << 20 | quad << 6 | \ 676 fn->hi_bits() << 16 | fn->hi_bit() << 7 | \ 677 fd->hi_bits() << 12 | fd->hi_bit() << 22 | \ 678 fm->hi_bits() | fm->hi_bit() << 5); \ 679 } 680 681 F(vmulI, 0x4 /* 0b0100 */, 0x9 /* 0b1001 */, 1, 0) // Vd = Vn * Vm (int) 682 F(vaddI, 0x4 /* 0b0100 */, 0x8 /* 0b1000 */, 0, 0) // Vd = Vn + Vm (int) 683 F(vsubI, 0x6 /* 0b0110 */, 0x8 /* 0b1000 */, 0, 0) // Vd = Vn - Vm (int) 684 F(vaddF, 0x4 /* 0b0100 */, 0xD /* 0b1101 */, 0, 0) // Vd = Vn + Vm (float) 685 F(vsubF, 0x4 /* 0b0100 */, 0xD /* 0b1101 */, 0, 1) // Vd = Vn - Vm (float) 686 F(vmulF, 0x6 /* 0b0110 */, 0xD /* 0b1101 */, 1, 0) // Vd = Vn * Vm (float) 687 F(vshlSI, 0x4 /* 0b0100 */, 0x4 /* 0b0100 */, 0, 0) // Vd = ashift(Vm,Vn) (int) 688 F(vshlUI, 0x6 /* 0b0110 */, 0x4 /* 0b0100 */, 0, 0) // Vd = lshift(Vm,Vn) (int) 689 F(_vandI, 0x4 /* 0b0100 */, 0x1 /* 0b0001 */, 1, 0) // Vd = Vn & Vm (int) 690 F(_vorI, 0x4 /* 0b0100 */, 0x1 /* 0b0001 */, 1, 1) // Vd = Vn | Vm (int) 691 F(_vxorI, 0x6 /* 0b0110 */, 0x1 /* 0b0001 */, 1, 0) // Vd = Vn ^ Vm (int) 692 #undef F 693 694 void vandI(FloatRegister fd, FloatRegister fn, FloatRegister fm, int quad) { 695 _vandI(fd, fn, fm, 0, quad); 696 } 697 void vorI(FloatRegister fd, FloatRegister fn, FloatRegister fm, int quad) { 698 _vorI(fd, fn, fm, 0, quad); 699 } 700 void vxorI(FloatRegister fd, FloatRegister fn, FloatRegister fm, int quad) { 701 _vxorI(fd, fn, fm, 0, quad); 702 } 703 704 void vneg(FloatRegister fd, FloatRegister fm, int size, int flt, int quad) { 705 CHECK_VFP_PRESENT; 706 assert(VM_Version::has_simd(), "simd instruction"); 707 assert(fd->lo_bit() == 0 && fm->lo_bit() == 0, 708 "single precision register?"); 709 assert(!quad || ((fd->hi_bits() | fm->hi_bits()) & 1) == 0, 710 "quad precision register?"); 711 emit_int32(0xf << 28 | 0x3B /* 0b00111011 */ << 20 | 0x1 /* 0b01 */ << 16 | 0x7 /* 0b111 */ << 7 | 712 size << 18 | quad << 6 | flt << 10 | 713 fd->hi_bits() << 12 | fd->hi_bit() << 22 | 714 fm->hi_bits() << 0 | fm->hi_bit() << 5); 715 } 716 717 void vnegI(FloatRegister fd, FloatRegister fm, int size, int quad) { 718 int flt = 0; 719 vneg(fd, fm, size, flt, quad); 720 } 721 722 void vshli(FloatRegister fd, FloatRegister fm, int size, int imm, int quad) { 723 CHECK_VFP_PRESENT; 724 assert(VM_Version::has_simd(), "simd instruction"); 725 assert(fd->lo_bit() == 0 && fm->lo_bit() == 0, 726 "single precision register?"); 727 assert(!quad || ((fd->hi_bits() | fm->hi_bits()) & 1) == 0, 728 "quad precision register?"); 729 730 if (imm >= size) { 731 // maximum shift gives all zeroes, direction doesn't matter, 732 // but only available for shift right 733 vshri(fd, fm, size, size, true /* unsigned */, quad); 734 return; 735 } 736 assert(imm >= 0 && imm < size, "out of range"); 737 738 int imm6 = 0; 739 int L = 0; 740 switch (size) { 741 case 8: 742 case 16: 743 case 32: 744 imm6 = size + imm ; 745 break; 746 case 64: 747 L = 1; 748 imm6 = imm ; 749 break; 750 default: 751 ShouldNotReachHere(); 752 } 753 emit_int32(0xf << 28 | 0x5 /* 0b00101 */ << 23 | 0x51 /* 0b01010001 */ << 4 | 754 imm6 << 16 | L << 7 | quad << 6 | 755 fd->hi_bits() << 12 | fd->hi_bit() << 22 | 756 fm->hi_bits() << 0 | fm->hi_bit() << 5); 757 } 758 759 void vshri(FloatRegister fd, FloatRegister fm, int size, int imm, 760 bool U /* unsigned */, int quad) { 761 CHECK_VFP_PRESENT; 762 assert(VM_Version::has_simd(), "simd instruction"); 763 assert(fd->lo_bit() == 0 && fm->lo_bit() == 0, 764 "single precision register?"); 765 assert(!quad || ((fd->hi_bits() | fm->hi_bits()) & 1) == 0, 766 "quad precision register?"); 767 assert(imm > 0, "out of range"); 768 if (imm >= size) { 769 // maximum shift (all zeroes) 770 imm = size; 771 } 772 int imm6 = 0; 773 int L = 0; 774 switch (size) { 775 case 8: 776 case 16: 777 case 32: 778 imm6 = 2 * size - imm ; 779 break; 780 case 64: 781 L = 1; 782 imm6 = 64 - imm ; 783 break; 784 default: 785 ShouldNotReachHere(); 786 } 787 emit_int32(0xf << 28 | 0x5 /* 0b00101 */ << 23 | 0x1 /* 0b00000001 */ << 4 | 788 imm6 << 16 | L << 7 | quad << 6 | U << 24 | 789 fd->hi_bits() << 12 | fd->hi_bit() << 22 | 790 fm->hi_bits() << 0 | fm->hi_bit() << 5); 791 } 792 void vshrUI(FloatRegister fd, FloatRegister fm, int size, int imm, int quad) { 793 vshri(fd, fm, size, imm, true /* unsigned */, quad); 794 } 795 void vshrSI(FloatRegister fd, FloatRegister fm, int size, int imm, int quad) { 796 vshri(fd, fm, size, imm, false /* signed */, quad); 797 } 798 799 // Extension opcodes where P,Q,R,S = 1 opcode is in Fn 800 #define F(mnemonic, N, opcode) \ 801 void mnemonic##d(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \ 802 CHECK_VFP_PRESENT; \ 803 assert(fd->lo_bit() == 0 && fm->hi_bit() == 0, "incorrect register?"); \ 804 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 805 double_cp_num | \ 806 fd->hi_bits() << 12 | fd->hi_bit() << 22 | \ 807 fm->hi_bits() | fm->lo_bit() << 5); \ 808 } \ 809 void mnemonic##s(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \ 810 CHECK_VFP_PRESENT; \ 811 assert(fd->hi_bit() == 0 && fm->hi_bit() == 0, "double precision register?"); \ 812 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 813 single_cp_num | \ 814 fd->hi_bits() << 12 | fd->lo_bit() << 22 | \ 815 fm->hi_bits() | fm->lo_bit() << 5); \ 816 } 817 818 F(fuito, 0, 0x8) // Unsigned integer to floating point conversion 819 F(fsito, 1, 0x8) // Signed integer to floating point conversion 820 #undef F 821 822 #define F(mnemonic, N, opcode) \ 823 void mnemonic##d(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \ 824 CHECK_VFP_PRESENT; \ 825 assert(fd->hi_bit() == 0 && fm->lo_bit() == 0, "incorrect register?"); \ 826 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 827 double_cp_num | \ 828 fd->hi_bits() << 12 | fd->lo_bit() << 22 | \ 829 fm->hi_bits() | fm->hi_bit() << 5); \ 830 } \ 831 void mnemonic##s(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \ 832 CHECK_VFP_PRESENT; \ 833 assert(fd->hi_bit() == 0 && fm->hi_bit() == 0, "double precision register?"); \ 834 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 835 single_cp_num | \ 836 fd->hi_bits() << 12 | fd->lo_bit() << 22 | \ 837 fm->hi_bits() | fm->lo_bit() << 5); \ 838 } 839 840 F(ftoui, 0, 0xc) // Float to unsigned int conversion 841 F(ftouiz, 1, 0xc) // Float to unsigned int conversion, RZ mode 842 F(ftosi, 0, 0xd) // Float to signed int conversion 843 F(ftosiz, 1, 0xd) // Float to signed int conversion, RZ mode 844 #undef F 845 846 #define F(mnemonic, N, opcode) \ 847 void mnemonic##d(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \ 848 CHECK_VFP_PRESENT; \ 849 assert(fd->hi_bit() == 0 && fm->lo_bit() == 0, "incorrect register?"); \ 850 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 851 double_cp_num | \ 852 fd->hi_bits() << 12 | fd->lo_bit() << 22 | \ 853 fm->hi_bits() | fm->hi_bit() << 5); \ 854 } \ 855 void mnemonic##s(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \ 856 CHECK_VFP_PRESENT; \ 857 assert(fd->lo_bit() == 0 && fm->hi_bit() == 0, "incorrect register?"); \ 858 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 859 single_cp_num | \ 860 fd->hi_bits() << 12 | fd->hi_bit() << 22 | \ 861 fm->hi_bits() | fm->lo_bit() << 5); \ 862 } 863 864 F(fcvtd, 1, 0x7) // Single->Double conversion 865 F(fcvts, 1, 0x7) // Double->Single conversion 866 #undef F 867 868 #define F(mnemonic, N, opcode) \ 869 void mnemonic##d(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \ 870 CHECK_VFP_PRESENT; \ 871 assert(fd->lo_bit() == 0 && fm->lo_bit() == 0, "single precision register?"); \ 872 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 873 double_cp_num | \ 874 fd->hi_bits() << 12 | fd->hi_bit() << 22 | \ 875 fm->hi_bits() | fm->hi_bit() << 5); \ 876 } \ 877 void mnemonic##s(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \ 878 CHECK_VFP_PRESENT; \ 879 assert(fd->hi_bit() == 0 && fm->hi_bit() == 0, "double precision register?"); \ 880 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 881 single_cp_num | \ 882 fd->hi_bits() << 12 | fd->lo_bit() << 22 | \ 883 fm->hi_bits() | fm->lo_bit() << 5); \ 884 } 885 886 F(fcpy, 0, 0x0) // Fd = Fm 887 F(fabs, 1, 0x0) // Fd = abs(Fm) 888 F(fneg, 0, 0x1) // Fd = -Fm 889 F(fsqrt, 1, 0x1) // Fd = sqrt(Fm) 890 F(fcmp, 0, 0x4) // Compare Fd with Fm no exceptions on quiet NANs 891 F(fcmpe, 1, 0x4) // Compare Fd with Fm with exceptions on quiet NANs 892 #undef F 893 894 // Opcodes with one operand only 895 #define F(mnemonic, N, opcode) \ 896 void mnemonic##d(FloatRegister fd, AsmCondition cond = al) { \ 897 CHECK_VFP_PRESENT; \ 898 assert(fd->lo_bit() == 0, "single precision register?"); \ 899 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 900 double_cp_num | fd->hi_bits() << 12 | fd->hi_bit() << 22); \ 901 } \ 902 void mnemonic##s(FloatRegister fd, AsmCondition cond = al) { \ 903 CHECK_VFP_PRESENT; \ 904 assert(fd->hi_bit() == 0, "double precision register?"); \ 905 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 906 single_cp_num | fd->hi_bits() << 12 | fd->lo_bit() << 22); \ 907 } 908 909 F(fcmpz, 0, 0x5) // Compare Fd with 0, no exceptions quiet NANs 910 F(fcmpez, 1, 0x5) // Compare Fd with 0, with exceptions quiet NANs 911 #undef F 912 913 // Float loads (L==1) and stores (L==0) 914 #define F(mnemonic, L) \ 915 void mnemonic##d(FloatRegister fd, Address addr, AsmCondition cond = al) { \ 916 CHECK_VFP_PRESENT; \ 917 assert(fd->lo_bit() == 0, "single precision register?"); \ 918 emit_int32(cond << 28 | 0xd << 24 | L << 20 | \ 919 fd->hi_bits() << 12 | fd->hi_bit() << 22 | \ 920 double_cp_num | addr.encoding_vfp()); \ 921 } \ 922 void mnemonic##s(FloatRegister fd, Address addr, AsmCondition cond = al) { \ 923 CHECK_VFP_PRESENT; \ 924 assert(fd->hi_bit() == 0, "double precision register?"); \ 925 emit_int32(cond << 28 | 0xd << 24 | L << 20 | \ 926 fd->hi_bits() << 12 | fd->lo_bit() << 22 | \ 927 single_cp_num | addr.encoding_vfp()); \ 928 } 929 930 F(fst, 0) // Store 1 register 931 F(fld, 1) // Load 1 register 932 #undef F 933 934 // Float load and store multiple 935 #define F(mnemonic, l, pu) \ 936 void mnemonic##d(Register rn, FloatRegisterSet reg_set, \ 937 AsmWriteback w = no_writeback, AsmCondition cond = al) { \ 938 CHECK_VFP_PRESENT; \ 939 assert(w == no_writeback || rn != PC, "unpredictable instruction"); \ 940 assert(!(w == no_writeback && pu == 2), "encoding constraint"); \ 941 assert((reg_set.encoding_d() & 1) == 0, "encoding constraint"); \ 942 emit_int32(cond << 28 | 6 << 25 | pu << 23 | w << 21 | l << 20 | \ 943 rn->encoding() << 16 | reg_set.encoding_d() | double_cp_num); \ 944 } \ 945 void mnemonic##s(Register rn, FloatRegisterSet reg_set, \ 946 AsmWriteback w = no_writeback, AsmCondition cond = al) { \ 947 CHECK_VFP_PRESENT; \ 948 assert(w == no_writeback || rn != PC, "unpredictable instruction"); \ 949 assert(!(w == no_writeback && pu == 2), "encoding constraint"); \ 950 emit_int32(cond << 28 | 6 << 25 | pu << 23 | w << 21 | l << 20 | \ 951 rn->encoding() << 16 | reg_set.encoding_s() | single_cp_num); \ 952 } 953 954 F(fldmia, 1, 1) F(fldmfd, 1, 1) 955 F(fldmdb, 1, 2) F(fldmea, 1, 2) 956 F(fstmia, 0, 1) F(fstmfd, 0, 1) 957 F(fstmdb, 0, 2) F(fstmea, 0, 2) 958 #undef F 959 960 // fconst{s,d} encoding: 961 // 31 28 27 23 22 21 20 19 16 15 12 10 9 8 7 4 3 0 962 // | cond | 11101 | D | 11 | imm4H | Vd | 101 | sz | 0000 | imm4L | 963 // sz = 0 for single precision, 1 otherwise 964 // Register number is Vd:D for single precision, D:Vd otherwise 965 // immediate value is imm4H:imm4L 966 967 void fconsts(FloatRegister fd, unsigned char imm_8, AsmCondition cond = al) { 968 CHECK_VFP_PRESENT; 969 assert(fd->hi_bit() == 0, "double precision register?"); 970 emit_int32(cond << 28 | 0xeb << 20 | single_cp_num | 971 fd->hi_bits() << 12 | fd->lo_bit() << 22 | (imm_8 & 0xf) | (imm_8 >> 4) << 16); 972 } 973 974 void fconstd(FloatRegister fd, unsigned char imm_8, AsmCondition cond = al) { 975 CHECK_VFP_PRESENT; 976 assert(fd->lo_bit() == 0, "double precision register?"); 977 emit_int32(cond << 28 | 0xeb << 20 | double_cp_num | 978 fd->hi_bits() << 12 | fd->hi_bit() << 22 | (imm_8 & 0xf) | (imm_8 >> 4) << 16); 979 } 980 981 // GPR <-> FPR transfers 982 void fmsr(FloatRegister fd, Register rd, AsmCondition cond = al) { 983 CHECK_VFP_PRESENT; 984 assert(fd->hi_bit() == 0, "double precision register?"); 985 emit_int32(cond << 28 | 0xe0 << 20 | single_cp_num | 1 << 4 | 986 fd->hi_bits() << 16 | fd->lo_bit() << 7 | rd->encoding() << 12); 987 } 988 989 void fmrs(Register rd, FloatRegister fd, AsmCondition cond = al) { 990 CHECK_VFP_PRESENT; 991 assert(fd->hi_bit() == 0, "double precision register?"); 992 emit_int32(cond << 28 | 0xe1 << 20 | single_cp_num | 1 << 4 | 993 fd->hi_bits() << 16 | fd->lo_bit() << 7 | rd->encoding() << 12); 994 } 995 996 void fmdrr(FloatRegister fd, Register rd, Register rn, AsmCondition cond = al) { 997 CHECK_VFP_PRESENT; 998 assert(fd->lo_bit() == 0, "single precision register?"); 999 emit_int32(cond << 28 | 0xc4 << 20 | double_cp_num | 1 << 4 | 1000 fd->hi_bits() | fd->hi_bit() << 5 | 1001 rn->encoding() << 16 | rd->encoding() << 12); 1002 } 1003 1004 void fmrrd(Register rd, Register rn, FloatRegister fd, AsmCondition cond = al) { 1005 CHECK_VFP_PRESENT; 1006 assert(fd->lo_bit() == 0, "single precision register?"); 1007 emit_int32(cond << 28 | 0xc5 << 20 | double_cp_num | 1 << 4 | 1008 fd->hi_bits() | fd->hi_bit() << 5 | 1009 rn->encoding() << 16 | rd->encoding() << 12); 1010 } 1011 1012 void fmstat(AsmCondition cond = al) { 1013 CHECK_VFP_PRESENT; 1014 emit_int32(cond << 28 | 0xef1fa10); 1015 } 1016 1017 void vmrs(Register rt, VFPSystemRegister sr, AsmCondition cond = al) { 1018 assert((sr->encoding() & (~0xf)) == 0, "what system register is that?"); 1019 emit_int32(cond << 28 | rt->encoding() << 12 | sr->encoding() << 16 | 0xef00a10); 1020 } 1021 1022 void vmsr(VFPSystemRegister sr, Register rt, AsmCondition cond = al) { 1023 assert((sr->encoding() & (~0xf)) == 0, "what system register is that?"); 1024 emit_int32(cond << 28 | rt->encoding() << 12 | sr->encoding() << 16 | 0xee00a10); 1025 } 1026 1027 void vcnt(FloatRegister Dd, FloatRegister Dm) { 1028 CHECK_VFP_PRESENT; 1029 // emitted at VM startup to detect whether the instruction is available 1030 assert(!VM_Version::is_initialized() || VM_Version::has_simd(), "simd instruction"); 1031 assert(Dd->lo_bit() == 0 && Dm->lo_bit() == 0, "single precision registers?"); 1032 emit_int32(0xf3b00500 | Dd->hi_bit() << 22 | Dd->hi_bits() << 12 | Dm->hi_bit() << 5 | Dm->hi_bits()); 1033 } 1034 1035 void vpaddl(FloatRegister Dd, FloatRegister Dm, int size, bool s) { 1036 CHECK_VFP_PRESENT; 1037 assert(VM_Version::has_simd(), "simd instruction"); 1038 assert(Dd->lo_bit() == 0 && Dm->lo_bit() == 0, "single precision registers?"); 1039 assert(size == 8 || size == 16 || size == 32, "unexpected size"); 1040 emit_int32(0xf3b00200 | Dd->hi_bit() << 22 | (size >> 4) << 18 | Dd->hi_bits() << 12 | (s ? 0 : 1) << 7 | Dm->hi_bit() << 5 | Dm->hi_bits()); 1041 } 1042 1043 void vld1(FloatRegister Dd, Address addr, VElem_Size size, int bits) { 1044 CHECK_VFP_PRESENT; 1045 assert(VM_Version::has_simd(), "simd instruction"); 1046 assert(Dd->lo_bit() == 0, "single precision registers?"); 1047 int align = 0; 1048 assert(bits == 128, "code assumption"); 1049 VLD_Type type = VLD1_TYPE_2_REGS; // 2x64 1050 emit_int32(0xf4200000 | Dd->hi_bit() << 22 | Dd->hi_bits() << 12 | type << 8 | size << 6 | align << 4 | addr.encoding_simd()); 1051 } 1052 1053 void vst1(FloatRegister Dd, Address addr, VElem_Size size, int bits) { 1054 CHECK_VFP_PRESENT; 1055 assert(VM_Version::has_simd(), "simd instruction"); 1056 assert(Dd->lo_bit() == 0, "single precision registers?"); 1057 int align = 0; 1058 assert(bits == 128, "code assumption"); 1059 VLD_Type type = VLD1_TYPE_2_REGS; // 2x64 1060 emit_int32(0xf4000000 | Dd->hi_bit() << 22 | Dd->hi_bits() << 12 | type << 8 | size << 6 | align << 4 | addr.encoding_simd()); 1061 } 1062 1063 void vmovI(FloatRegister Dd, int imm8, VElem_Size size, int quad) { 1064 CHECK_VFP_PRESENT; 1065 assert(VM_Version::has_simd(), "simd instruction"); 1066 assert(Dd->lo_bit() == 0, "single precision register?"); 1067 assert(!quad || (Dd->hi_bits() & 1) == 0, "quad precision register?"); 1068 assert(imm8 >= 0 && imm8 < 256, "out of range"); 1069 int op; 1070 int cmode; 1071 switch (size) { 1072 case VELEM_SIZE_8: 1073 op = 0; 1074 cmode = 0xE /* 0b1110 */; 1075 break; 1076 case VELEM_SIZE_16: 1077 op = 0; 1078 cmode = 0x8 /* 0b1000 */; 1079 break; 1080 case VELEM_SIZE_32: 1081 op = 0; 1082 cmode = 0x0 /* 0b0000 */; 1083 break; 1084 default: 1085 ShouldNotReachHere(); 1086 return; 1087 } 1088 emit_int32(0xf << 28 | 0x1 << 25 | 0x1 << 23 | 0x1 << 4 | 1089 (imm8 >> 7) << 24 | ((imm8 & 0x70) >> 4) << 16 | (imm8 & 0xf) | 1090 quad << 6 | op << 5 | cmode << 8 | 1091 Dd->hi_bits() << 12 | Dd->hi_bit() << 22); 1092 } 1093 1094 void vdupI(FloatRegister Dd, Register Rs, VElem_Size size, int quad, 1095 AsmCondition cond = al) { 1096 CHECK_VFP_PRESENT; 1097 assert(VM_Version::has_simd(), "simd instruction"); 1098 assert(Dd->lo_bit() == 0, "single precision register?"); 1099 assert(!quad || (Dd->hi_bits() & 1) == 0, "quad precision register?"); 1100 int b; 1101 int e; 1102 switch (size) { 1103 case VELEM_SIZE_8: 1104 b = 1; 1105 e = 0; 1106 break; 1107 case VELEM_SIZE_16: 1108 b = 0; 1109 e = 1; 1110 break; 1111 case VELEM_SIZE_32: 1112 b = 0; 1113 e = 0; 1114 break; 1115 default: 1116 ShouldNotReachHere(); 1117 return; 1118 } 1119 emit_int32(cond << 28 | 0x1D /* 0b11101 */ << 23 | 0xB /* 0b1011 */ << 8 | 0x1 << 4 | 1120 quad << 21 | b << 22 | e << 5 | Rs->encoding() << 12 | 1121 Dd->hi_bits() << 16 | Dd->hi_bit() << 7); 1122 } 1123 1124 void vdup(FloatRegister Dd, FloatRegister Ds, int index, int size, int quad) { 1125 CHECK_VFP_PRESENT; 1126 assert(VM_Version::has_simd(), "simd instruction"); 1127 assert(Dd->lo_bit() == 0, "single precision register?"); 1128 assert(Ds->lo_bit() == 0, "single precision register?"); 1129 assert(!quad || (Dd->hi_bits() & 1) == 0, "quad precision register?"); 1130 int range = 64 / size; 1131 assert(index < range, "overflow"); 1132 int imm4; 1133 switch (size) { 1134 case 8: 1135 assert((index & 0x7 /* 0b111 */) == index, "overflow"); 1136 imm4 = index << 1 | 0x1 /* 0b0001 */; 1137 break; 1138 case 16: 1139 assert((index & 0x3 /* 0b11 */) == index, "overflow"); 1140 imm4 = index << 2 | 0x2 /* 0b0010 */; 1141 break; 1142 case 32: 1143 assert((index & 0x1 /* 0b1 */) == index, "overflow"); 1144 imm4 = index << 3 | 0x4 /* 0b0100 */; 1145 break; 1146 default: 1147 ShouldNotReachHere(); 1148 return; 1149 } 1150 emit_int32(0xF /* 0b1111 */ << 28 | 0x3B /* 0b00111011 */ << 20 | 0x6 /* 0b110 */ << 9 | 1151 quad << 6 | imm4 << 16 | 1152 Dd->hi_bits() << 12 | Dd->hi_bit() << 22 | 1153 Ds->hi_bits() << 00 | Ds->hi_bit() << 5); 1154 } 1155 1156 void vdupF(FloatRegister Dd, FloatRegister Ss, int quad) { 1157 int index = 0; 1158 FloatRegister Ds = as_FloatRegister(Ss->encoding() & ~1); 1159 if (Ss->lo_bit() != 0) { 1160 /* odd S register */ 1161 assert(Ds->successor() == Ss, "bad reg"); 1162 index = 1; 1163 } else { 1164 /* even S register */ 1165 assert(Ds == Ss, "bad reg"); 1166 } 1167 vdup(Dd, Ds, index, 32, quad); 1168 } 1169 1170 void vrev(FloatRegister Dd, FloatRegister Dm, int quad, int region_size, VElem_Size size) { 1171 CHECK_VFP_PRESENT; 1172 assert(VM_Version::has_simd(), "simd instruction"); 1173 assert(Dd->lo_bit() == 0, "single precision register?"); 1174 assert(Dm->lo_bit() == 0, "single precision register?"); 1175 assert(!quad || ((Dd->hi_bits() | Dm->hi_bits()) & 1) == 0, 1176 "quad precision register?"); 1177 unsigned int op = 0; 1178 switch (region_size) { 1179 case 16: op = 0x2; /*0b10*/ break; 1180 case 32: op = 0x1; /*0b01*/ break; 1181 case 64: op = 0x0; /*0b00*/ break; 1182 default: assert(false, "encoding constraint"); 1183 } 1184 emit_int32(0xf << 28 | 0x7 << 23 | Dd->hi_bit() << 22 | 0x3 << 20 | 1185 size << 18 | Dd->hi_bits() << 12 | op << 7 | quad << 6 | Dm->hi_bit() << 5 | 1186 Dm->hi_bits()); 1187 } 1188 1189 void veor(FloatRegister Dd, FloatRegister Dn, FloatRegister Dm, int quad) { 1190 CHECK_VFP_PRESENT; 1191 assert(VM_Version::has_simd(), "simd instruction"); 1192 assert(Dd->lo_bit() == 0, "single precision register?"); 1193 assert(Dm->lo_bit() == 0, "single precision register?"); 1194 assert(Dn->lo_bit() == 0, "single precision register?"); 1195 assert(!quad || ((Dd->hi_bits() | Dm->hi_bits() | Dn->hi_bits()) & 1) == 0, 1196 "quad precision register?"); 1197 1198 emit_int32(0xf << 28 | 0x3 << 24 | Dd->hi_bit() << 22 | Dn->hi_bits() << 16 | 1199 Dd->hi_bits() << 12 | 0x1 << 8 | Dn->hi_bit() << 7 | quad << 6 | 1200 Dm->hi_bit() << 5 | 0x1 << 4 | Dm->hi_bits()); 1201 } 1202 1203 1204 Assembler(CodeBuffer* code) : AbstractAssembler(code) {} 1205 1206 #ifdef COMPILER2 1207 typedef VFP::double_num double_num; 1208 typedef VFP::float_num float_num; 1209 #endif 1210 }; 1211 1212 #ifdef __SOFTFP__ 1213 // Soft float function declarations 1214 extern "C" { 1215 extern float __aeabi_fadd(float, float); 1216 extern float __aeabi_fmul(float, float); 1217 extern float __aeabi_fsub(float, float); 1218 extern float __aeabi_fdiv(float, float); 1219 1220 extern double __aeabi_dadd(double, double); 1221 extern double __aeabi_dmul(double, double); 1222 extern double __aeabi_dsub(double, double); 1223 extern double __aeabi_ddiv(double, double); 1224 1225 extern double __aeabi_f2d(float); 1226 extern float __aeabi_d2f(double); 1227 extern float __aeabi_i2f(int); 1228 extern double __aeabi_i2d(int); 1229 extern int __aeabi_f2iz(float); 1230 1231 extern int __aeabi_fcmpeq(float, float); 1232 extern int __aeabi_fcmplt(float, float); 1233 extern int __aeabi_fcmple(float, float); 1234 extern int __aeabi_fcmpge(float, float); 1235 extern int __aeabi_fcmpgt(float, float); 1236 1237 extern int __aeabi_dcmpeq(double, double); 1238 extern int __aeabi_dcmplt(double, double); 1239 extern int __aeabi_dcmple(double, double); 1240 extern int __aeabi_dcmpge(double, double); 1241 extern int __aeabi_dcmpgt(double, double); 1242 1243 // Optional wrapper around SoftFloat-3e for 1244 // calculation accuracy improvement. See CR 6757269, JDK-8215902. 1245 extern float __aeabi_fadd_extlib(float, float); 1246 extern float __aeabi_fsub_extlib(float, float); 1247 extern double __aeabi_dadd_extlib(double, double); 1248 extern double __aeabi_dsub_extlib(double, double); 1249 }; 1250 #endif // __SOFTFP__ 1251 1252 1253 #endif // CPU_ARM_VM_ASSEMBLER_ARM_32_HPP