1 /* 2 * Copyright (c) 2008, 2019, 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_ASSEMBLER_ARM_32_HPP 26 #define CPU_ARM_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::is_initialized() || 438 (VM_Version::arm_arch() >= 7 && VM_Version::has_multiprocessing_extensions()), 439 "PLDW is available on ARMv7 with Multiprocessing Extensions only"); 440 emit_int32(0xf510f000 | addr.encoding2()); 441 } 442 443 void svc(int imm_24, AsmCondition cond = al) { 444 assert((imm_24 >> 24) == 0, "encoding constraint"); 445 emit_int32(cond << 28 | 0xf << 24 | imm_24); 446 } 447 448 void ubfx(Register rd, Register rn, unsigned int lsb, unsigned int width, AsmCondition cond = al) { 449 assert(VM_Version::arm_arch() >= 7, "no ubfx on this processor"); 450 assert(width > 0, "must be"); 451 assert(lsb < 32, "must be"); 452 emit_int32(cond << 28 | 0x3f << 21 | (width - 1) << 16 | rd->encoding() << 12 | 453 lsb << 7 | 0x5 << 4 | rn->encoding()); 454 } 455 456 void uxtb(Register rd, Register rm, unsigned int rotation = 0, AsmCondition cond = al) { 457 assert(VM_Version::arm_arch() >= 7, "no uxtb on this processor"); 458 assert((rotation % 8) == 0 && (rotation <= 24), "encoding constraint"); 459 emit_int32(cond << 28 | 0x6e << 20 | 0xf << 16 | rd->encoding() << 12 | 460 (rotation >> 3) << 10 | 0x7 << 4 | rm->encoding()); 461 } 462 463 // ARM Memory Barriers 464 // 465 // There are two types of memory barriers defined for the ARM processor 466 // DataSynchronizationBarrier and DataMemoryBarrier 467 // 468 // The Linux kernel uses the DataMemoryBarrier for all of it's 469 // memory barrier operations (smp_mb, smp_rmb, smp_wmb) 470 // 471 // There are two forms of each barrier instruction. 472 // The mcr forms are supported on armv5 and newer architectures 473 // 474 // The dmb, dsb instructions were added in armv7 475 // architectures and are compatible with their mcr 476 // predecessors. 477 // 478 // Here are the encodings for future reference: 479 // 480 // DataSynchronizationBarrier (dsb) 481 // on ARMv7 - emit_int32(0xF57FF04F) 482 // 483 // on ARMv5+ - mcr p15, 0, Rtmp, c7, c10, 4 on earlier processors 484 // emit_int32(0xe << 28 | 0xe << 24 | 0x7 << 16 | Rtmp->encoding() << 12 | 485 // 0xf << 8 | 0x9 << 4 | 0xa); 486 // 487 // DataMemoryBarrier (dmb) 488 // on ARMv7 - emit_int32(0xF57FF05F) 489 // 490 // on ARMv5+ - mcr p15, 0, Rtmp, c7, c10, 5 on earlier processors 491 // emit_int32(0xe << 28 | 0xe << 24 | 0x7 << 16 | Rtmp->encoding() << 12 | 492 // 0xf << 8 | 0xb << 4 | 0xa); 493 // 494 495 enum DMB_Opt { 496 DMB_all = 0xf, 497 DMB_st = 0xe, 498 }; 499 500 void dmb(DMB_Opt opt, Register reg) { 501 if (VM_Version::arm_arch() >= 7) { 502 emit_int32(0xF57FF050 | opt); 503 } else if (VM_Version::arm_arch() == 6) { 504 bool preserve_tmp = (reg == noreg); 505 if(preserve_tmp) { 506 reg = Rtemp; 507 str(reg, Address(SP, -wordSize, pre_indexed)); 508 } 509 mov(reg, 0); 510 // DataMemoryBarrier 511 emit_int32(0xe << 28 | 512 0xe << 24 | 513 0x7 << 16 | 514 reg->encoding() << 12 | 515 0xf << 8 | 516 0xb << 4 | 517 0xa); 518 if(preserve_tmp) { 519 ldr(reg, Address(SP, wordSize, post_indexed)); 520 } 521 } 522 } 523 524 void dsb(Register reg) { 525 if (VM_Version::arm_arch() >= 7) { 526 emit_int32(0xF57FF04F); 527 } else { 528 bool preserve_tmp = (reg == noreg); 529 if(preserve_tmp) { 530 reg = Rtemp; 531 str(reg, Address(SP, -wordSize, pre_indexed)); 532 } 533 mov(reg, 0); 534 // DataSynchronizationBarrier 535 emit_int32(0xe << 28 | 536 0xe << 24 | 537 0x7 << 16 | 538 reg->encoding() << 12 | 539 0xf << 8 | 540 0x9 << 4 | 541 0xa); 542 if(preserve_tmp) { 543 ldr(reg, Address(SP, wordSize, post_indexed)); 544 } 545 } 546 } 547 548 549 #define F(mnemonic, b) \ 550 void mnemonic(Register rd, Register rm, Register rn, AsmCondition cond = al) { \ 551 assert(rn != rm && rn != rd, "unpredictable instruction"); \ 552 emit_int32(cond << 28 | 0x2 << 23 | b << 22 | rn->encoding() << 16 | \ 553 rd->encoding() << 12 | 9 << 4 | rm->encoding()); \ 554 } 555 556 F(swp, 0) 557 F(swpb, 1) 558 #undef F 559 560 // Branches 561 562 #define F(mnemonic, l) \ 563 void mnemonic(Register rm, AsmCondition cond = al) { \ 564 emit_int32(cond << 28 | 0x012fff10 | l << 5 | rm->encoding()); \ 565 } 566 567 F(bx, 0) 568 F(blx, 1) 569 #undef F 570 571 #define F(mnemonic, l) \ 572 void mnemonic(address target, AsmCondition cond = al) { \ 573 unsigned int offset = (unsigned int)(target - pc() - 8); \ 574 assert((offset & 3) == 0, "bad alignment"); \ 575 assert((offset >> 25) == 0 || ((int)offset >> 25) == -1, "offset is too large"); \ 576 emit_int32(cond << 28 | l << 24 | offset << 6 >> 8); \ 577 } 578 579 F(b, 0xa) 580 F(bl, 0xb) 581 #undef F 582 583 void udf(int imm_16) { 584 assert((imm_16 >> 16) == 0, "encoding constraint"); 585 emit_int32(0xe7f000f0 | (imm_16 & 0xfff0) << 8 | (imm_16 & 0xf)); 586 } 587 588 // ARMv7 instructions 589 590 #define F(mnemonic, wt) \ 591 void mnemonic(Register rd, int imm_16, AsmCondition cond = al) { \ 592 assert((imm_16 >> 16) == 0, "encoding constraint"); \ 593 emit_int32(cond << 28 | wt << 20 | rd->encoding() << 12 | \ 594 (imm_16 & 0xf000) << 4 | (imm_16 & 0xfff)); \ 595 } 596 597 F(movw, 0x30) 598 F(movt, 0x34) 599 #undef F 600 601 // VFP Support 602 603 // Checks that VFP instructions are not used in SOFTFP mode. 604 #ifdef __SOFTFP__ 605 #define CHECK_VFP_PRESENT ShouldNotReachHere() 606 #else 607 #define CHECK_VFP_PRESENT 608 #endif // __SOFTFP__ 609 610 static const int single_cp_num = 0xa00; 611 static const int double_cp_num = 0xb00; 612 613 // Bits P, Q, R, S collectively form the opcode 614 #define F(mnemonic, P, Q, R, S) \ 615 void mnemonic##d(FloatRegister fd, FloatRegister fn, FloatRegister fm, \ 616 AsmCondition cond = al) { \ 617 CHECK_VFP_PRESENT; \ 618 assert(fn->lo_bit() == 0 && fd->lo_bit() == 0 && fm->lo_bit() == 0, "single precision register?"); \ 619 emit_int32(cond << 28 | 0x7 << 25 | double_cp_num | \ 620 P << 23 | Q << 21 | R << 20 | S << 6 | \ 621 fn->hi_bits() << 16 | fn->hi_bit() << 7 | \ 622 fd->hi_bits() << 12 | fd->hi_bit() << 22 | \ 623 fm->hi_bits() | fm->hi_bit() << 5); \ 624 } \ 625 void mnemonic##s(FloatRegister fd, FloatRegister fn, FloatRegister fm, \ 626 AsmCondition cond = al) { \ 627 assert(fn->hi_bit() == 0 && fd->hi_bit() == 0 && fm->hi_bit() == 0, "double precision register?"); \ 628 CHECK_VFP_PRESENT; \ 629 emit_int32(cond << 28 | 0x7 << 25 | single_cp_num | \ 630 P << 23 | Q << 21 | R << 20 | S << 6 | \ 631 fn->hi_bits() << 16 | fn->lo_bit() << 7 | \ 632 fd->hi_bits() << 12 | fd->lo_bit() << 22 | \ 633 fm->hi_bits() | fm->lo_bit() << 5); \ 634 } 635 636 F(fmac, 0, 0, 0, 0) // Fd = Fd + (Fn * Fm) 637 F(fnmac, 0, 0, 0, 1) // Fd = Fd - (Fn * Fm) 638 F(fmsc, 0, 0, 1, 0) // Fd = -Fd + (Fn * Fm) 639 F(fnmsc, 0, 0, 1, 1) // Fd = -Fd - (Fn * Fm) 640 641 F(fmul, 0, 1, 0, 0) // Fd = Fn * Fm 642 F(fnmul, 0, 1, 0, 1) // Fd = -(Fn * Fm) 643 F(fadd, 0, 1, 1, 0) // Fd = Fn + Fm 644 F(fsub, 0, 1, 1, 1) // Fd = Fn - Fm 645 F(fdiv, 1, 0, 0, 0) // Fd = Fn / Fm 646 #undef F 647 648 enum VElem_Size { 649 VELEM_SIZE_8 = 0x00, 650 VELEM_SIZE_16 = 0x01, 651 VELEM_SIZE_32 = 0x02, 652 VELEM_SIZE_64 = 0x03 653 }; 654 655 enum VLD_Type { 656 VLD1_TYPE_1_REG = 0x7 /* 0b0111 */, 657 VLD1_TYPE_2_REGS = 0xA /* 0b1010 */, 658 VLD1_TYPE_3_REGS = 0x6 /* 0b0110 */, 659 VLD1_TYPE_4_REGS = 0x2 /* 0b0010 */ 660 }; 661 662 enum VFloat_Arith_Size { 663 VFA_SIZE_F32 = 0x0 /* 0b0 */, 664 }; 665 666 // Bits P, Q, R, S collectively form the opcode 667 #define F(mnemonic, P, Q, R, S) \ 668 void mnemonic(FloatRegister fd, FloatRegister fn, FloatRegister fm, \ 669 int size, int quad) { \ 670 CHECK_VFP_PRESENT; \ 671 assert(VM_Version::has_simd(), "simd instruction"); \ 672 assert(fn->lo_bit() == 0 && fd->lo_bit() == 0 && fm->lo_bit() == 0, \ 673 "single precision register?"); \ 674 assert(!quad || ((fn->hi_bits() | fd->hi_bits() | fm->hi_bits()) & 1) == 0, \ 675 "quad precision register?"); \ 676 emit_int32(0xf << 28 | P << 23 | Q << 8 | R << 4 | \ 677 S << 21 | size << 20 | quad << 6 | \ 678 fn->hi_bits() << 16 | fn->hi_bit() << 7 | \ 679 fd->hi_bits() << 12 | fd->hi_bit() << 22 | \ 680 fm->hi_bits() | fm->hi_bit() << 5); \ 681 } 682 683 F(vmulI, 0x4 /* 0b0100 */, 0x9 /* 0b1001 */, 1, 0) // Vd = Vn * Vm (int) 684 F(vaddI, 0x4 /* 0b0100 */, 0x8 /* 0b1000 */, 0, 0) // Vd = Vn + Vm (int) 685 F(vsubI, 0x6 /* 0b0110 */, 0x8 /* 0b1000 */, 0, 0) // Vd = Vn - Vm (int) 686 F(vaddF, 0x4 /* 0b0100 */, 0xD /* 0b1101 */, 0, 0) // Vd = Vn + Vm (float) 687 F(vsubF, 0x4 /* 0b0100 */, 0xD /* 0b1101 */, 0, 1) // Vd = Vn - Vm (float) 688 F(vmulF, 0x6 /* 0b0110 */, 0xD /* 0b1101 */, 1, 0) // Vd = Vn * Vm (float) 689 F(vshlSI, 0x4 /* 0b0100 */, 0x4 /* 0b0100 */, 0, 0) // Vd = ashift(Vm,Vn) (int) 690 F(vshlUI, 0x6 /* 0b0110 */, 0x4 /* 0b0100 */, 0, 0) // Vd = lshift(Vm,Vn) (int) 691 F(_vandI, 0x4 /* 0b0100 */, 0x1 /* 0b0001 */, 1, 0) // Vd = Vn & Vm (int) 692 F(_vorI, 0x4 /* 0b0100 */, 0x1 /* 0b0001 */, 1, 1) // Vd = Vn | Vm (int) 693 F(_vxorI, 0x6 /* 0b0110 */, 0x1 /* 0b0001 */, 1, 0) // Vd = Vn ^ Vm (int) 694 #undef F 695 696 void vandI(FloatRegister fd, FloatRegister fn, FloatRegister fm, int quad) { 697 _vandI(fd, fn, fm, 0, quad); 698 } 699 void vorI(FloatRegister fd, FloatRegister fn, FloatRegister fm, int quad) { 700 _vorI(fd, fn, fm, 0, quad); 701 } 702 void vxorI(FloatRegister fd, FloatRegister fn, FloatRegister fm, int quad) { 703 _vxorI(fd, fn, fm, 0, quad); 704 } 705 706 void vneg(FloatRegister fd, FloatRegister fm, int size, int flt, int quad) { 707 CHECK_VFP_PRESENT; 708 assert(VM_Version::has_simd(), "simd instruction"); 709 assert(fd->lo_bit() == 0 && fm->lo_bit() == 0, 710 "single precision register?"); 711 assert(!quad || ((fd->hi_bits() | fm->hi_bits()) & 1) == 0, 712 "quad precision register?"); 713 emit_int32(0xf << 28 | 0x3B /* 0b00111011 */ << 20 | 0x1 /* 0b01 */ << 16 | 0x7 /* 0b111 */ << 7 | 714 size << 18 | quad << 6 | flt << 10 | 715 fd->hi_bits() << 12 | fd->hi_bit() << 22 | 716 fm->hi_bits() << 0 | fm->hi_bit() << 5); 717 } 718 719 void vnegI(FloatRegister fd, FloatRegister fm, int size, int quad) { 720 int flt = 0; 721 vneg(fd, fm, size, flt, quad); 722 } 723 724 void vshli(FloatRegister fd, FloatRegister fm, int size, int imm, int quad) { 725 CHECK_VFP_PRESENT; 726 assert(VM_Version::has_simd(), "simd instruction"); 727 assert(fd->lo_bit() == 0 && fm->lo_bit() == 0, 728 "single precision register?"); 729 assert(!quad || ((fd->hi_bits() | fm->hi_bits()) & 1) == 0, 730 "quad precision register?"); 731 732 if (imm >= size) { 733 // maximum shift gives all zeroes, direction doesn't matter, 734 // but only available for shift right 735 vshri(fd, fm, size, size, true /* unsigned */, quad); 736 return; 737 } 738 assert(imm >= 0 && imm < size, "out of range"); 739 740 int imm6 = 0; 741 int L = 0; 742 switch (size) { 743 case 8: 744 case 16: 745 case 32: 746 imm6 = size + imm ; 747 break; 748 case 64: 749 L = 1; 750 imm6 = imm ; 751 break; 752 default: 753 ShouldNotReachHere(); 754 } 755 emit_int32(0xf << 28 | 0x5 /* 0b00101 */ << 23 | 0x51 /* 0b01010001 */ << 4 | 756 imm6 << 16 | L << 7 | quad << 6 | 757 fd->hi_bits() << 12 | fd->hi_bit() << 22 | 758 fm->hi_bits() << 0 | fm->hi_bit() << 5); 759 } 760 761 void vshri(FloatRegister fd, FloatRegister fm, int size, int imm, 762 bool U /* unsigned */, int quad) { 763 CHECK_VFP_PRESENT; 764 assert(VM_Version::has_simd(), "simd instruction"); 765 assert(fd->lo_bit() == 0 && fm->lo_bit() == 0, 766 "single precision register?"); 767 assert(!quad || ((fd->hi_bits() | fm->hi_bits()) & 1) == 0, 768 "quad precision register?"); 769 assert(imm > 0, "out of range"); 770 if (imm >= size) { 771 // maximum shift (all zeroes) 772 imm = size; 773 } 774 int imm6 = 0; 775 int L = 0; 776 switch (size) { 777 case 8: 778 case 16: 779 case 32: 780 imm6 = 2 * size - imm ; 781 break; 782 case 64: 783 L = 1; 784 imm6 = 64 - imm ; 785 break; 786 default: 787 ShouldNotReachHere(); 788 } 789 emit_int32(0xf << 28 | 0x5 /* 0b00101 */ << 23 | 0x1 /* 0b00000001 */ << 4 | 790 imm6 << 16 | L << 7 | quad << 6 | U << 24 | 791 fd->hi_bits() << 12 | fd->hi_bit() << 22 | 792 fm->hi_bits() << 0 | fm->hi_bit() << 5); 793 } 794 void vshrUI(FloatRegister fd, FloatRegister fm, int size, int imm, int quad) { 795 vshri(fd, fm, size, imm, true /* unsigned */, quad); 796 } 797 void vshrSI(FloatRegister fd, FloatRegister fm, int size, int imm, int quad) { 798 vshri(fd, fm, size, imm, false /* signed */, quad); 799 } 800 801 // Extension opcodes where P,Q,R,S = 1 opcode is in Fn 802 #define F(mnemonic, N, opcode) \ 803 void mnemonic##d(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \ 804 CHECK_VFP_PRESENT; \ 805 assert(fd->lo_bit() == 0 && fm->hi_bit() == 0, "incorrect register?"); \ 806 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 807 double_cp_num | \ 808 fd->hi_bits() << 12 | fd->hi_bit() << 22 | \ 809 fm->hi_bits() | fm->lo_bit() << 5); \ 810 } \ 811 void mnemonic##s(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \ 812 CHECK_VFP_PRESENT; \ 813 assert(fd->hi_bit() == 0 && fm->hi_bit() == 0, "double precision register?"); \ 814 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 815 single_cp_num | \ 816 fd->hi_bits() << 12 | fd->lo_bit() << 22 | \ 817 fm->hi_bits() | fm->lo_bit() << 5); \ 818 } 819 820 F(fuito, 0, 0x8) // Unsigned integer to floating point conversion 821 F(fsito, 1, 0x8) // Signed integer to floating point conversion 822 #undef F 823 824 #define F(mnemonic, N, opcode) \ 825 void mnemonic##d(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \ 826 CHECK_VFP_PRESENT; \ 827 assert(fd->hi_bit() == 0 && fm->lo_bit() == 0, "incorrect register?"); \ 828 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 829 double_cp_num | \ 830 fd->hi_bits() << 12 | fd->lo_bit() << 22 | \ 831 fm->hi_bits() | fm->hi_bit() << 5); \ 832 } \ 833 void mnemonic##s(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \ 834 CHECK_VFP_PRESENT; \ 835 assert(fd->hi_bit() == 0 && fm->hi_bit() == 0, "double precision register?"); \ 836 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 837 single_cp_num | \ 838 fd->hi_bits() << 12 | fd->lo_bit() << 22 | \ 839 fm->hi_bits() | fm->lo_bit() << 5); \ 840 } 841 842 F(ftoui, 0, 0xc) // Float to unsigned int conversion 843 F(ftouiz, 1, 0xc) // Float to unsigned int conversion, RZ mode 844 F(ftosi, 0, 0xd) // Float to signed int conversion 845 F(ftosiz, 1, 0xd) // Float to signed int conversion, RZ mode 846 #undef F 847 848 #define F(mnemonic, N, opcode) \ 849 void mnemonic##d(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \ 850 CHECK_VFP_PRESENT; \ 851 assert(fd->hi_bit() == 0 && fm->lo_bit() == 0, "incorrect register?"); \ 852 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 853 double_cp_num | \ 854 fd->hi_bits() << 12 | fd->lo_bit() << 22 | \ 855 fm->hi_bits() | fm->hi_bit() << 5); \ 856 } \ 857 void mnemonic##s(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \ 858 CHECK_VFP_PRESENT; \ 859 assert(fd->lo_bit() == 0 && fm->hi_bit() == 0, "incorrect register?"); \ 860 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 861 single_cp_num | \ 862 fd->hi_bits() << 12 | fd->hi_bit() << 22 | \ 863 fm->hi_bits() | fm->lo_bit() << 5); \ 864 } 865 866 F(fcvtd, 1, 0x7) // Single->Double conversion 867 F(fcvts, 1, 0x7) // Double->Single conversion 868 #undef F 869 870 #define F(mnemonic, N, opcode) \ 871 void mnemonic##d(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \ 872 CHECK_VFP_PRESENT; \ 873 assert(fd->lo_bit() == 0 && fm->lo_bit() == 0, "single precision register?"); \ 874 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 875 double_cp_num | \ 876 fd->hi_bits() << 12 | fd->hi_bit() << 22 | \ 877 fm->hi_bits() | fm->hi_bit() << 5); \ 878 } \ 879 void mnemonic##s(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \ 880 CHECK_VFP_PRESENT; \ 881 assert(fd->hi_bit() == 0 && fm->hi_bit() == 0, "double precision register?"); \ 882 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 883 single_cp_num | \ 884 fd->hi_bits() << 12 | fd->lo_bit() << 22 | \ 885 fm->hi_bits() | fm->lo_bit() << 5); \ 886 } 887 888 F(fcpy, 0, 0x0) // Fd = Fm 889 F(fabs, 1, 0x0) // Fd = abs(Fm) 890 F(fneg, 0, 0x1) // Fd = -Fm 891 F(fsqrt, 1, 0x1) // Fd = sqrt(Fm) 892 F(fcmp, 0, 0x4) // Compare Fd with Fm no exceptions on quiet NANs 893 F(fcmpe, 1, 0x4) // Compare Fd with Fm with exceptions on quiet NANs 894 #undef F 895 896 // Opcodes with one operand only 897 #define F(mnemonic, N, opcode) \ 898 void mnemonic##d(FloatRegister fd, AsmCondition cond = al) { \ 899 CHECK_VFP_PRESENT; \ 900 assert(fd->lo_bit() == 0, "single precision register?"); \ 901 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 902 double_cp_num | fd->hi_bits() << 12 | fd->hi_bit() << 22); \ 903 } \ 904 void mnemonic##s(FloatRegister fd, AsmCondition cond = al) { \ 905 CHECK_VFP_PRESENT; \ 906 assert(fd->hi_bit() == 0, "double precision register?"); \ 907 emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \ 908 single_cp_num | fd->hi_bits() << 12 | fd->lo_bit() << 22); \ 909 } 910 911 F(fcmpz, 0, 0x5) // Compare Fd with 0, no exceptions quiet NANs 912 F(fcmpez, 1, 0x5) // Compare Fd with 0, with exceptions quiet NANs 913 #undef F 914 915 // Float loads (L==1) and stores (L==0) 916 #define F(mnemonic, L) \ 917 void mnemonic##d(FloatRegister fd, Address addr, AsmCondition cond = al) { \ 918 CHECK_VFP_PRESENT; \ 919 assert(fd->lo_bit() == 0, "single precision register?"); \ 920 emit_int32(cond << 28 | 0xd << 24 | L << 20 | \ 921 fd->hi_bits() << 12 | fd->hi_bit() << 22 | \ 922 double_cp_num | addr.encoding_vfp()); \ 923 } \ 924 void mnemonic##s(FloatRegister fd, Address addr, AsmCondition cond = al) { \ 925 CHECK_VFP_PRESENT; \ 926 assert(fd->hi_bit() == 0, "double precision register?"); \ 927 emit_int32(cond << 28 | 0xd << 24 | L << 20 | \ 928 fd->hi_bits() << 12 | fd->lo_bit() << 22 | \ 929 single_cp_num | addr.encoding_vfp()); \ 930 } 931 932 F(fst, 0) // Store 1 register 933 F(fld, 1) // Load 1 register 934 #undef F 935 936 // Float load and store multiple 937 #define F(mnemonic, l, pu) \ 938 void mnemonic##d(Register rn, FloatRegisterSet reg_set, \ 939 AsmWriteback w = no_writeback, AsmCondition cond = al) { \ 940 CHECK_VFP_PRESENT; \ 941 assert(w == no_writeback || rn != PC, "unpredictable instruction"); \ 942 assert(!(w == no_writeback && pu == 2), "encoding constraint"); \ 943 assert((reg_set.encoding_d() & 1) == 0, "encoding constraint"); \ 944 emit_int32(cond << 28 | 6 << 25 | pu << 23 | w << 21 | l << 20 | \ 945 rn->encoding() << 16 | reg_set.encoding_d() | double_cp_num); \ 946 } \ 947 void mnemonic##s(Register rn, FloatRegisterSet reg_set, \ 948 AsmWriteback w = no_writeback, AsmCondition cond = al) { \ 949 CHECK_VFP_PRESENT; \ 950 assert(w == no_writeback || rn != PC, "unpredictable instruction"); \ 951 assert(!(w == no_writeback && pu == 2), "encoding constraint"); \ 952 emit_int32(cond << 28 | 6 << 25 | pu << 23 | w << 21 | l << 20 | \ 953 rn->encoding() << 16 | reg_set.encoding_s() | single_cp_num); \ 954 } 955 956 F(fldmia, 1, 1) F(fldmfd, 1, 1) 957 F(fldmdb, 1, 2) F(fldmea, 1, 2) 958 F(fstmia, 0, 1) F(fstmfd, 0, 1) 959 F(fstmdb, 0, 2) F(fstmea, 0, 2) 960 #undef F 961 962 // fconst{s,d} encoding: 963 // 31 28 27 23 22 21 20 19 16 15 12 10 9 8 7 4 3 0 964 // | cond | 11101 | D | 11 | imm4H | Vd | 101 | sz | 0000 | imm4L | 965 // sz = 0 for single precision, 1 otherwise 966 // Register number is Vd:D for single precision, D:Vd otherwise 967 // immediate value is imm4H:imm4L 968 969 void fconsts(FloatRegister fd, unsigned char imm_8, AsmCondition cond = al) { 970 CHECK_VFP_PRESENT; 971 assert(fd->hi_bit() == 0, "double precision register?"); 972 emit_int32(cond << 28 | 0xeb << 20 | single_cp_num | 973 fd->hi_bits() << 12 | fd->lo_bit() << 22 | (imm_8 & 0xf) | (imm_8 >> 4) << 16); 974 } 975 976 void fconstd(FloatRegister fd, unsigned char imm_8, AsmCondition cond = al) { 977 CHECK_VFP_PRESENT; 978 assert(fd->lo_bit() == 0, "double precision register?"); 979 emit_int32(cond << 28 | 0xeb << 20 | double_cp_num | 980 fd->hi_bits() << 12 | fd->hi_bit() << 22 | (imm_8 & 0xf) | (imm_8 >> 4) << 16); 981 } 982 983 // GPR <-> FPR transfers 984 void fmsr(FloatRegister fd, Register rd, AsmCondition cond = al) { 985 CHECK_VFP_PRESENT; 986 assert(fd->hi_bit() == 0, "double precision register?"); 987 emit_int32(cond << 28 | 0xe0 << 20 | single_cp_num | 1 << 4 | 988 fd->hi_bits() << 16 | fd->lo_bit() << 7 | rd->encoding() << 12); 989 } 990 991 void fmrs(Register rd, FloatRegister fd, AsmCondition cond = al) { 992 CHECK_VFP_PRESENT; 993 assert(fd->hi_bit() == 0, "double precision register?"); 994 emit_int32(cond << 28 | 0xe1 << 20 | single_cp_num | 1 << 4 | 995 fd->hi_bits() << 16 | fd->lo_bit() << 7 | rd->encoding() << 12); 996 } 997 998 void fmdrr(FloatRegister fd, Register rd, Register rn, AsmCondition cond = al) { 999 CHECK_VFP_PRESENT; 1000 assert(fd->lo_bit() == 0, "single precision register?"); 1001 emit_int32(cond << 28 | 0xc4 << 20 | double_cp_num | 1 << 4 | 1002 fd->hi_bits() | fd->hi_bit() << 5 | 1003 rn->encoding() << 16 | rd->encoding() << 12); 1004 } 1005 1006 void fmrrd(Register rd, Register rn, FloatRegister fd, AsmCondition cond = al) { 1007 CHECK_VFP_PRESENT; 1008 assert(fd->lo_bit() == 0, "single precision register?"); 1009 emit_int32(cond << 28 | 0xc5 << 20 | double_cp_num | 1 << 4 | 1010 fd->hi_bits() | fd->hi_bit() << 5 | 1011 rn->encoding() << 16 | rd->encoding() << 12); 1012 } 1013 1014 void fmstat(AsmCondition cond = al) { 1015 CHECK_VFP_PRESENT; 1016 emit_int32(cond << 28 | 0xef1fa10); 1017 } 1018 1019 void vmrs(Register rt, VFPSystemRegister sr, AsmCondition cond = al) { 1020 assert((sr->encoding() & (~0xf)) == 0, "what system register is that?"); 1021 emit_int32(cond << 28 | rt->encoding() << 12 | sr->encoding() << 16 | 0xef00a10); 1022 } 1023 1024 void vmsr(VFPSystemRegister sr, Register rt, AsmCondition cond = al) { 1025 assert((sr->encoding() & (~0xf)) == 0, "what system register is that?"); 1026 emit_int32(cond << 28 | rt->encoding() << 12 | sr->encoding() << 16 | 0xee00a10); 1027 } 1028 1029 void vcnt(FloatRegister Dd, FloatRegister Dm) { 1030 CHECK_VFP_PRESENT; 1031 // emitted at VM startup to detect whether the instruction is available 1032 assert(!VM_Version::is_initialized() || VM_Version::has_simd(), "simd instruction"); 1033 assert(Dd->lo_bit() == 0 && Dm->lo_bit() == 0, "single precision registers?"); 1034 emit_int32(0xf3b00500 | Dd->hi_bit() << 22 | Dd->hi_bits() << 12 | Dm->hi_bit() << 5 | Dm->hi_bits()); 1035 } 1036 1037 void vpaddl(FloatRegister Dd, FloatRegister Dm, int size, bool s) { 1038 CHECK_VFP_PRESENT; 1039 assert(VM_Version::has_simd(), "simd instruction"); 1040 assert(Dd->lo_bit() == 0 && Dm->lo_bit() == 0, "single precision registers?"); 1041 assert(size == 8 || size == 16 || size == 32, "unexpected size"); 1042 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()); 1043 } 1044 1045 void vld1(FloatRegister Dd, Address addr, VElem_Size size, int bits) { 1046 CHECK_VFP_PRESENT; 1047 assert(VM_Version::has_simd(), "simd instruction"); 1048 assert(Dd->lo_bit() == 0, "single precision registers?"); 1049 int align = 0; 1050 assert(bits == 128, "code assumption"); 1051 VLD_Type type = VLD1_TYPE_2_REGS; // 2x64 1052 emit_int32(0xf4200000 | Dd->hi_bit() << 22 | Dd->hi_bits() << 12 | type << 8 | size << 6 | align << 4 | addr.encoding_simd()); 1053 } 1054 1055 void vst1(FloatRegister Dd, Address addr, VElem_Size size, int bits) { 1056 CHECK_VFP_PRESENT; 1057 assert(VM_Version::has_simd(), "simd instruction"); 1058 assert(Dd->lo_bit() == 0, "single precision registers?"); 1059 int align = 0; 1060 assert(bits == 128, "code assumption"); 1061 VLD_Type type = VLD1_TYPE_2_REGS; // 2x64 1062 emit_int32(0xf4000000 | Dd->hi_bit() << 22 | Dd->hi_bits() << 12 | type << 8 | size << 6 | align << 4 | addr.encoding_simd()); 1063 } 1064 1065 void vmovI(FloatRegister Dd, int imm8, VElem_Size size, int quad) { 1066 CHECK_VFP_PRESENT; 1067 assert(VM_Version::has_simd(), "simd instruction"); 1068 assert(Dd->lo_bit() == 0, "single precision register?"); 1069 assert(!quad || (Dd->hi_bits() & 1) == 0, "quad precision register?"); 1070 assert(imm8 >= 0 && imm8 < 256, "out of range"); 1071 int op; 1072 int cmode; 1073 switch (size) { 1074 case VELEM_SIZE_8: 1075 op = 0; 1076 cmode = 0xE /* 0b1110 */; 1077 break; 1078 case VELEM_SIZE_16: 1079 op = 0; 1080 cmode = 0x8 /* 0b1000 */; 1081 break; 1082 case VELEM_SIZE_32: 1083 op = 0; 1084 cmode = 0x0 /* 0b0000 */; 1085 break; 1086 default: 1087 ShouldNotReachHere(); 1088 return; 1089 } 1090 emit_int32(0xf << 28 | 0x1 << 25 | 0x1 << 23 | 0x1 << 4 | 1091 (imm8 >> 7) << 24 | ((imm8 & 0x70) >> 4) << 16 | (imm8 & 0xf) | 1092 quad << 6 | op << 5 | cmode << 8 | 1093 Dd->hi_bits() << 12 | Dd->hi_bit() << 22); 1094 } 1095 1096 void vdupI(FloatRegister Dd, Register Rs, VElem_Size size, int quad, 1097 AsmCondition cond = al) { 1098 CHECK_VFP_PRESENT; 1099 assert(VM_Version::has_simd(), "simd instruction"); 1100 assert(Dd->lo_bit() == 0, "single precision register?"); 1101 assert(!quad || (Dd->hi_bits() & 1) == 0, "quad precision register?"); 1102 int b; 1103 int e; 1104 switch (size) { 1105 case VELEM_SIZE_8: 1106 b = 1; 1107 e = 0; 1108 break; 1109 case VELEM_SIZE_16: 1110 b = 0; 1111 e = 1; 1112 break; 1113 case VELEM_SIZE_32: 1114 b = 0; 1115 e = 0; 1116 break; 1117 default: 1118 ShouldNotReachHere(); 1119 return; 1120 } 1121 emit_int32(cond << 28 | 0x1D /* 0b11101 */ << 23 | 0xB /* 0b1011 */ << 8 | 0x1 << 4 | 1122 quad << 21 | b << 22 | e << 5 | Rs->encoding() << 12 | 1123 Dd->hi_bits() << 16 | Dd->hi_bit() << 7); 1124 } 1125 1126 void vdup(FloatRegister Dd, FloatRegister Ds, int index, int size, int quad) { 1127 CHECK_VFP_PRESENT; 1128 assert(VM_Version::has_simd(), "simd instruction"); 1129 assert(Dd->lo_bit() == 0, "single precision register?"); 1130 assert(Ds->lo_bit() == 0, "single precision register?"); 1131 assert(!quad || (Dd->hi_bits() & 1) == 0, "quad precision register?"); 1132 int range = 64 / size; 1133 assert(index < range, "overflow"); 1134 int imm4; 1135 switch (size) { 1136 case 8: 1137 assert((index & 0x7 /* 0b111 */) == index, "overflow"); 1138 imm4 = index << 1 | 0x1 /* 0b0001 */; 1139 break; 1140 case 16: 1141 assert((index & 0x3 /* 0b11 */) == index, "overflow"); 1142 imm4 = index << 2 | 0x2 /* 0b0010 */; 1143 break; 1144 case 32: 1145 assert((index & 0x1 /* 0b1 */) == index, "overflow"); 1146 imm4 = index << 3 | 0x4 /* 0b0100 */; 1147 break; 1148 default: 1149 ShouldNotReachHere(); 1150 return; 1151 } 1152 emit_int32(0xF /* 0b1111 */ << 28 | 0x3B /* 0b00111011 */ << 20 | 0x6 /* 0b110 */ << 9 | 1153 quad << 6 | imm4 << 16 | 1154 Dd->hi_bits() << 12 | Dd->hi_bit() << 22 | 1155 Ds->hi_bits() << 00 | Ds->hi_bit() << 5); 1156 } 1157 1158 void vdupF(FloatRegister Dd, FloatRegister Ss, int quad) { 1159 int index = 0; 1160 FloatRegister Ds = as_FloatRegister(Ss->encoding() & ~1); 1161 if (Ss->lo_bit() != 0) { 1162 /* odd S register */ 1163 assert(Ds->successor() == Ss, "bad reg"); 1164 index = 1; 1165 } else { 1166 /* even S register */ 1167 assert(Ds == Ss, "bad reg"); 1168 } 1169 vdup(Dd, Ds, index, 32, quad); 1170 } 1171 1172 void vrev(FloatRegister Dd, FloatRegister Dm, int quad, int region_size, VElem_Size size) { 1173 CHECK_VFP_PRESENT; 1174 assert(VM_Version::has_simd(), "simd instruction"); 1175 assert(Dd->lo_bit() == 0, "single precision register?"); 1176 assert(Dm->lo_bit() == 0, "single precision register?"); 1177 assert(!quad || ((Dd->hi_bits() | Dm->hi_bits()) & 1) == 0, 1178 "quad precision register?"); 1179 unsigned int op = 0; 1180 switch (region_size) { 1181 case 16: op = 0x2; /*0b10*/ break; 1182 case 32: op = 0x1; /*0b01*/ break; 1183 case 64: op = 0x0; /*0b00*/ break; 1184 default: assert(false, "encoding constraint"); 1185 } 1186 emit_int32(0xf << 28 | 0x7 << 23 | Dd->hi_bit() << 22 | 0x3 << 20 | 1187 size << 18 | Dd->hi_bits() << 12 | op << 7 | quad << 6 | Dm->hi_bit() << 5 | 1188 Dm->hi_bits()); 1189 } 1190 1191 void veor(FloatRegister Dd, FloatRegister Dn, FloatRegister Dm, int quad) { 1192 CHECK_VFP_PRESENT; 1193 assert(VM_Version::has_simd(), "simd instruction"); 1194 assert(Dd->lo_bit() == 0, "single precision register?"); 1195 assert(Dm->lo_bit() == 0, "single precision register?"); 1196 assert(Dn->lo_bit() == 0, "single precision register?"); 1197 assert(!quad || ((Dd->hi_bits() | Dm->hi_bits() | Dn->hi_bits()) & 1) == 0, 1198 "quad precision register?"); 1199 1200 emit_int32(0xf << 28 | 0x3 << 24 | Dd->hi_bit() << 22 | Dn->hi_bits() << 16 | 1201 Dd->hi_bits() << 12 | 0x1 << 8 | Dn->hi_bit() << 7 | quad << 6 | 1202 Dm->hi_bit() << 5 | 0x1 << 4 | Dm->hi_bits()); 1203 } 1204 1205 1206 Assembler(CodeBuffer* code) : AbstractAssembler(code) {} 1207 1208 #ifdef COMPILER2 1209 typedef VFP::double_num double_num; 1210 typedef VFP::float_num float_num; 1211 #endif 1212 }; 1213 1214 #ifdef __SOFTFP__ 1215 // Soft float function declarations 1216 extern "C" { 1217 extern float __aeabi_fadd(float, float); 1218 extern float __aeabi_fmul(float, float); 1219 extern float __aeabi_fsub(float, float); 1220 extern float __aeabi_fdiv(float, float); 1221 1222 extern double __aeabi_dadd(double, double); 1223 extern double __aeabi_dmul(double, double); 1224 extern double __aeabi_dsub(double, double); 1225 extern double __aeabi_ddiv(double, double); 1226 1227 extern double __aeabi_f2d(float); 1228 extern float __aeabi_d2f(double); 1229 extern float __aeabi_i2f(int); 1230 extern double __aeabi_i2d(int); 1231 extern int __aeabi_f2iz(float); 1232 1233 extern int __aeabi_fcmpeq(float, float); 1234 extern int __aeabi_fcmplt(float, float); 1235 extern int __aeabi_fcmple(float, float); 1236 extern int __aeabi_fcmpge(float, float); 1237 extern int __aeabi_fcmpgt(float, float); 1238 1239 extern int __aeabi_dcmpeq(double, double); 1240 extern int __aeabi_dcmplt(double, double); 1241 extern int __aeabi_dcmple(double, double); 1242 extern int __aeabi_dcmpge(double, double); 1243 extern int __aeabi_dcmpgt(double, double); 1244 1245 // Imported code from glibc soft-fp bundle for 1246 // calculation accuracy improvement. See CR 6757269. 1247 extern double __aeabi_fadd_glibc(float, float); 1248 extern double __aeabi_fsub_glibc(float, float); 1249 extern double __aeabi_dadd_glibc(double, double); 1250 extern double __aeabi_dsub_glibc(double, double); 1251 }; 1252 #endif // __SOFTFP__ 1253 1254 1255 #endif // CPU_ARM_ASSEMBLER_ARM_32_HPP