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