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