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