Path: blob/master/src/hotspot/cpu/arm/assembler_arm_32.hpp
40930 views
/*1* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef CPU_ARM_ASSEMBLER_ARM_32_HPP25#define CPU_ARM_ASSEMBLER_ARM_32_HPP2627// ARM Addressing Mode 1 - Data processing operands28class AsmOperand {29private:30int _encoding;3132void initialize_rotated_imm(unsigned int imm);3334void encode(int imm_8) {35if ((imm_8 >> 8) == 0) {36_encoding = 1 << 25 | imm_8; // the most common case37} else {38initialize_rotated_imm((unsigned int)imm_8); // slow case39}40}4142void encode(Register rm, AsmShift shift, int shift_imm) {43assert((shift_imm >> 5) == 0, "encoding constraint");44_encoding = shift_imm << 7 | shift << 5 | rm->encoding();45}4647public:4849AsmOperand(Register reg) {50_encoding = reg->encoding();51}5253AsmOperand(int imm_8) {54encode(imm_8);55}5657AsmOperand(ByteSize bytesize_8) :58AsmOperand(in_bytes(bytesize_8)) {}5960AsmOperand(Register rm, AsmShift shift, int shift_imm) {61encode(rm,shift,shift_imm);62}6364AsmOperand(Register rm, AsmShift shift, Register rs) {65assert(rm != PC && rs != PC, "unpredictable instruction");66_encoding = rs->encoding() << 8 | shift << 5 | 1 << 4 | rm->encoding();67}6869AsmOperand(RegisterOrConstant offset, AsmShift shift = lsl, int shift_imm = 0) {70if (offset.is_register()) {71encode(offset.as_register(), shift, shift_imm);72} else {73assert(shift == lsl,"shift type not yet encoded");74int imm_8 = ((int)offset.as_constant()) << shift_imm;75encode(imm_8);76}77}7879int encoding() const {80return _encoding;81}8283bool is_immediate() const {84return _encoding & (1 << 25) ? true : false;85}8687Register base_register() const {88assert(!is_immediate(), "is_immediate, no base reg");89return as_Register(_encoding & 15);90}9192static bool is_rotated_imm(unsigned int imm);93};949596// ARM Addressing Mode 4 - Load and store multiple97class RegisterSet {98private:99int _encoding;100101RegisterSet(int encoding) {102_encoding = encoding;103}104105public:106107RegisterSet(Register reg) {108_encoding = 1 << reg->encoding();109}110111RegisterSet() {112_encoding = 0;113}114115RegisterSet(Register first, Register last) {116assert(first < last, "encoding constraint");117_encoding = (1 << (last->encoding() + 1)) - (1 << first->encoding());118}119120friend RegisterSet operator | (const RegisterSet set1, const RegisterSet set2) {121assert((set1._encoding & set2._encoding) == 0,122"encoding constraint");123return RegisterSet(set1._encoding | set2._encoding);124}125126int encoding() const {127return _encoding;128}129130bool contains(Register reg) const {131return (_encoding & (1 << reg->encoding())) != 0;132}133134// number of registers in the set135int size() const {136int count = 0;137unsigned int remaining = (unsigned int) _encoding;138while (remaining != 0) {139if ((remaining & 1) != 0) count++;140remaining >>= 1;141}142return count;143}144};145146#if R9_IS_SCRATCHED147#define R9ifScratched RegisterSet(R9)148#else149#define R9ifScratched RegisterSet()150#endif151152// ARM Addressing Mode 5 - Load and store multiple VFP registers153class FloatRegisterSet {154private:155int _encoding;156157public:158159FloatRegisterSet(FloatRegister reg) {160if (reg->hi_bit() == 0) {161_encoding = reg->hi_bits() << 12 | reg->lo_bit() << 22 | 1;162} else {163assert (reg->lo_bit() == 0, "impossible encoding");164_encoding = reg->hi_bits() << 12 | reg->hi_bit() << 22 | 1;165}166}167168FloatRegisterSet(FloatRegister first, int count) {169assert(count >= 1, "encoding constraint");170if (first->hi_bit() == 0) {171_encoding = first->hi_bits() << 12 | first->lo_bit() << 22 | count;172} else {173assert (first->lo_bit() == 0, "impossible encoding");174_encoding = first->hi_bits() << 12 | first->hi_bit() << 22 | count;175}176}177178int encoding_s() const {179return _encoding;180}181182int encoding_d() const {183assert((_encoding & 0xFF) <= 16, "no more than 16 double registers" );184return (_encoding & 0xFFFFFF00) | ((_encoding & 0xFF) << 1);185}186187};188189190class Assembler : public AbstractAssembler {191192public:193194static const int LogInstructionSize = 2;195static const int InstructionSize = 1 << LogInstructionSize;196197//---< calculate length of instruction >---198// We just use the values set above.199// instruction must start at passed address200static unsigned int instr_len(unsigned char *instr) { return InstructionSize; }201202//---< longest instructions >---203static unsigned int instr_maxlen() { return InstructionSize; }204205static inline AsmCondition inverse(AsmCondition cond) {206assert ((cond != al) && (cond != nv), "AL and NV conditions cannot be inversed");207return (AsmCondition)((int)cond ^ 1);208}209210// Returns true if given value can be used as immediate in arithmetic (add/sub/cmp/cmn) instructions.211static inline bool is_arith_imm_in_range(intx value) {212return AsmOperand::is_rotated_imm(value);213}214215// Arithmetic instructions216217#define F(mnemonic, opcode) \218void mnemonic(Register rd, Register rn, AsmOperand operand, AsmCondition cond = al) { \219emit_int32(cond << 28 | opcode << 21 | rn->encoding() << 16 | \220rd->encoding() << 12 | operand.encoding()); \221} \222void mnemonic##s(Register rd, Register rn, AsmOperand operand, AsmCondition cond = al) { \223emit_int32(cond << 28 | opcode << 21 | 1 << 20 | rn->encoding() << 16 | \224rd->encoding() << 12 | operand.encoding()); \225}226227F(andr, 0)228F(eor, 1)229F(sub, 2)230F(rsb, 3)231F(add, 4)232F(adc, 5)233F(sbc, 6)234F(rsc, 7)235F(orr, 12)236F(bic, 14)237#undef F238239#define F(mnemonic, opcode) \240void mnemonic(Register rn, AsmOperand operand, AsmCondition cond = al) { \241emit_int32(cond << 28 | opcode << 21 | 1 << 20 | rn->encoding() << 16 | \242operand.encoding()); \243}244245F(tst, 8)246F(teq, 9)247F(cmp, 10)248F(cmn, 11)249#undef F250251#define F(mnemonic, opcode) \252void mnemonic(Register rd, AsmOperand operand, AsmCondition cond = al) { \253emit_int32(cond << 28 | opcode << 21 | rd->encoding() << 12 | \254operand.encoding()); \255} \256void mnemonic##s(Register rd, AsmOperand operand, AsmCondition cond = al) { \257emit_int32(cond << 28 | opcode << 21 | 1 << 20 | rd->encoding() << 12 | \258operand.encoding()); \259}260261F(mov, 13)262F(mvn, 15)263#undef F264265void msr(uint fields, AsmOperand operand, AsmCondition cond = al) {266assert((operand.encoding() & (1<<25)) || ((operand.encoding() & 0xff0) == 0), "invalid addressing mode");267emit_int32(cond << 28 | 1 << 24 | 1 << 21 | fields << 16 | 0xf << 12 | operand.encoding());268}269270void mrs(uint fields, Register Rd, AsmCondition cond = al) {271emit_int32(cond << 28 | 1 << 24 | (fields|0xf) << 16 | (Rd->encoding() << 12));272}273274275enum {276CPSR = 0x00, CPSR_c = 0x01, CPSR_x = 0x02, CPSR_xc = 0x03,277CPSR_s = 0x004, CPSR_sc = 0x05, CPSR_sx = 0x06, CPSR_sxc = 0x07,278CPSR_f = 0x08, CPSR_fc = 0x09, CPSR_fx = 0x0a, CPSR_fxc = 0x0b,279CPSR_fs = 0x0c, CPSR_fsc = 0x0d, CPSR_fsx = 0x0e, CPSR_fsxc = 0x0f,280SPSR = 0x40, SPSR_c = 0x41, SPSR_x = 0x42, SPSR_xc = 0x43,281SPSR_s = 0x44, SPSR_sc = 0x45, SPSR_sx = 0x46, SPSR_sxc = 0x47,282SPSR_f = 0x48, SPSR_fc = 0x49, SPSR_fx = 0x4a, SPSR_fxc = 0x4b,283SPSR_fs = 0x4c, SPSR_fsc = 0x4d, SPSR_fsx = 0x4e, SPSR_fsxc = 0x4f284};285286#define F(mnemonic, opcode) \287void mnemonic(Register rdlo, Register rdhi, Register rm, Register rs, \288AsmCondition cond = al) { \289emit_int32(cond << 28 | opcode << 21 | rdhi->encoding() << 16 | \290rdlo->encoding() << 12 | rs->encoding() << 8 | 0x9 << 4 | rm->encoding()); \291} \292void mnemonic##s(Register rdlo, Register rdhi, Register rm, Register rs, \293AsmCondition cond = al) { \294emit_int32(cond << 28 | opcode << 21 | 1 << 20 | rdhi->encoding() << 16 | \295rdlo->encoding() << 12 | rs->encoding() << 8 | 0x9 << 4 | rm->encoding()); \296}297298F(umull, 4)299F(umlal, 5)300F(smull, 6)301F(smlal, 7)302#undef F303304void mul(Register rd, Register rm, Register rs, AsmCondition cond = al) {305emit_int32(cond << 28 | rd->encoding() << 16 |306rs->encoding() << 8 | 0x9 << 4 | rm->encoding());307}308309void muls(Register rd, Register rm, Register rs, AsmCondition cond = al) {310emit_int32(cond << 28 | 1 << 20 | rd->encoding() << 16 |311rs->encoding() << 8 | 0x9 << 4 | rm->encoding());312}313314void mla(Register rd, Register rm, Register rs, Register rn, AsmCondition cond = al) {315emit_int32(cond << 28 | 1 << 21 | rd->encoding() << 16 |316rn->encoding() << 12 | rs->encoding() << 8 | 0x9 << 4 | rm->encoding());317}318319void mlas(Register rd, Register rm, Register rs, Register rn, AsmCondition cond = al) {320emit_int32(cond << 28 | 1 << 21 | 1 << 20 | rd->encoding() << 16 |321rn->encoding() << 12 | rs->encoding() << 8 | 0x9 << 4 | rm->encoding());322}323324// Loads and stores325326#define F(mnemonic, l, b) \327void mnemonic(Register rd, Address addr, AsmCondition cond = al) { \328emit_int32(cond << 28 | 1 << 26 | b << 22 | l << 20 | \329rd->encoding() << 12 | addr.encoding2()); \330}331332F(ldr, 1, 0)333F(ldrb, 1, 1)334F(str, 0, 0)335F(strb, 0, 1)336#undef F337338#undef F339340#define F(mnemonic, l, sh, even) \341void mnemonic(Register rd, Address addr, AsmCondition cond = al) { \342assert(!even || (rd->encoding() & 1) == 0, "must be even"); \343emit_int32(cond << 28 | l << 20 | rd->encoding() << 12 | \3441 << 7 | sh << 5 | 1 << 4 | addr.encoding3()); \345}346347F(strh, 0, 1, false)348F(ldrh, 1, 1, false)349F(ldrsb, 1, 2, false)350F(ldrsh, 1, 3, false)351F(strd, 0, 3, true)352353#undef F354355void ldrd(Register rd, Address addr, AsmCondition cond = al) {356assert((rd->encoding() & 1) == 0, "must be even");357assert(!addr.index()->is_valid() ||358(addr.index()->encoding() != rd->encoding() &&359addr.index()->encoding() != (rd->encoding()+1)), "encoding constraint");360emit_int32(cond << 28 | rd->encoding() << 12 | 0xD /* 0b1101 */ << 4 | addr.encoding3());361}362363#define F(mnemonic, l, pu) \364void mnemonic(Register rn, RegisterSet reg_set, \365AsmWriteback w = no_writeback, AsmCondition cond = al) { \366assert(reg_set.encoding() != 0 && (w == no_writeback || \367(reg_set.encoding() & (1 << rn->encoding())) == 0), \368"unpredictable instruction"); \369emit_int32(cond << 28 | 4 << 25 | pu << 23 | w << 21 | l << 20 | \370rn->encoding() << 16 | reg_set.encoding()); \371}372373F(ldmda, 1, 0) F(ldmfa, 1, 0)374F(ldmia, 1, 1) F(ldmfd, 1, 1)375F(ldmdb, 1, 2) F(ldmea, 1, 2)376F(ldmib, 1, 3) F(ldmed, 1, 3)377F(stmda, 0, 0) F(stmed, 0, 0)378F(stmia, 0, 1) F(stmea, 0, 1)379F(stmdb, 0, 2) F(stmfd, 0, 2)380F(stmib, 0, 3) F(stmfa, 0, 3)381#undef F382383void ldrex(Register rd, Address addr, AsmCondition cond = al) {384assert(rd != PC, "unpredictable instruction");385emit_int32(cond << 28 | 0x19 << 20 | addr.encoding_ex() |386rd->encoding() << 12 | 0xf9f);387}388389void strex(Register rs, Register rd, Address addr, AsmCondition cond = al) {390assert(rd != PC && rs != PC &&391rs != rd && rs != addr.base(), "unpredictable instruction");392emit_int32(cond << 28 | 0x18 << 20 | addr.encoding_ex() |393rs->encoding() << 12 | 0xf90 | rd->encoding());394}395396void ldrexd(Register rd, Address addr, AsmCondition cond = al) {397assert(rd != PC, "unpredictable instruction");398emit_int32(cond << 28 | 0x1B << 20 | addr.encoding_ex() |399rd->encoding() << 12 | 0xf9f);400}401402void strexd(Register rs, Register rd, Address addr, AsmCondition cond = al) {403assert(rd != PC && rs != PC &&404rs != rd && rs != addr.base(), "unpredictable instruction");405emit_int32(cond << 28 | 0x1A << 20 | addr.encoding_ex() |406rs->encoding() << 12 | 0xf90 | rd->encoding());407}408409void clrex() {410emit_int32(0xF << 28 | 0x57 << 20 | 0xFF << 12 | 0x01f);411}412413// Miscellaneous instructions414415void clz(Register rd, Register rm, AsmCondition cond = al) {416emit_int32(cond << 28 | 0x016f0f10 | rd->encoding() << 12 | rm->encoding());417}418419void rev(Register rd, Register rm, AsmCondition cond = al) {420emit_int32(cond << 28 | 0x06bf0f30 | rd->encoding() << 12 | rm->encoding());421}422423void rev16(Register rd, Register rm, AsmCondition cond = al) {424emit_int32(cond << 28 | 0x6bf0fb0 | rd->encoding() << 12 | rm->encoding());425}426427void revsh(Register rd, Register rm, AsmCondition cond = al) {428emit_int32(cond << 28 | 0x6ff0fb0 | rd->encoding() << 12 | rm->encoding());429}430431void rbit(Register rd, Register rm, AsmCondition cond = al) {432emit_int32(cond << 28 | 0x6ff0f30 | rd->encoding() << 12 | rm->encoding());433}434435void pld(Address addr) {436emit_int32(0xf550f000 | addr.encoding2());437}438439void pldw(Address addr) {440assert(!VM_Version::is_initialized() ||441(VM_Version::arm_arch() >= 7 && VM_Version::has_multiprocessing_extensions()),442"PLDW is available on ARMv7 with Multiprocessing Extensions only");443emit_int32(0xf510f000 | addr.encoding2());444}445446void svc(int imm_24, AsmCondition cond = al) {447assert((imm_24 >> 24) == 0, "encoding constraint");448emit_int32(cond << 28 | 0xf << 24 | imm_24);449}450451void ubfx(Register rd, Register rn, unsigned int lsb, unsigned int width, AsmCondition cond = al) {452assert(VM_Version::arm_arch() >= 7, "no ubfx on this processor");453assert(width > 0, "must be");454assert(lsb < 32, "must be");455emit_int32(cond << 28 | 0x3f << 21 | (width - 1) << 16 | rd->encoding() << 12 |456lsb << 7 | 0x5 << 4 | rn->encoding());457}458459void uxtb(Register rd, Register rm, unsigned int rotation = 0, AsmCondition cond = al) {460assert(VM_Version::arm_arch() >= 7, "no uxtb on this processor");461assert((rotation % 8) == 0 && (rotation <= 24), "encoding constraint");462emit_int32(cond << 28 | 0x6e << 20 | 0xf << 16 | rd->encoding() << 12 |463(rotation >> 3) << 10 | 0x7 << 4 | rm->encoding());464}465466// ARM Memory Barriers467//468// There are two types of memory barriers defined for the ARM processor469// DataSynchronizationBarrier and DataMemoryBarrier470//471// The Linux kernel uses the DataMemoryBarrier for all of it's472// memory barrier operations (smp_mb, smp_rmb, smp_wmb)473//474// There are two forms of each barrier instruction.475// The mcr forms are supported on armv5 and newer architectures476//477// The dmb, dsb instructions were added in armv7478// architectures and are compatible with their mcr479// predecessors.480//481// Here are the encodings for future reference:482//483// DataSynchronizationBarrier (dsb)484// on ARMv7 - emit_int32(0xF57FF04F)485//486// on ARMv5+ - mcr p15, 0, Rtmp, c7, c10, 4 on earlier processors487// emit_int32(0xe << 28 | 0xe << 24 | 0x7 << 16 | Rtmp->encoding() << 12 |488// 0xf << 8 | 0x9 << 4 | 0xa);489//490// DataMemoryBarrier (dmb)491// on ARMv7 - emit_int32(0xF57FF05F)492//493// on ARMv5+ - mcr p15, 0, Rtmp, c7, c10, 5 on earlier processors494// emit_int32(0xe << 28 | 0xe << 24 | 0x7 << 16 | Rtmp->encoding() << 12 |495// 0xf << 8 | 0xb << 4 | 0xa);496//497498enum DMB_Opt {499DMB_all = 0xf,500DMB_st = 0xe,501};502503void dmb(DMB_Opt opt, Register reg) {504if (VM_Version::arm_arch() >= 7) {505emit_int32(0xF57FF050 | opt);506} else if (VM_Version::arm_arch() == 6) {507bool preserve_tmp = (reg == noreg);508if(preserve_tmp) {509reg = Rtemp;510str(reg, Address(SP, -wordSize, pre_indexed));511}512mov(reg, 0);513// DataMemoryBarrier514emit_int32(0xe << 28 |5150xe << 24 |5160x7 << 16 |517reg->encoding() << 12 |5180xf << 8 |5190xb << 4 |5200xa);521if(preserve_tmp) {522ldr(reg, Address(SP, wordSize, post_indexed));523}524}525}526527void dsb(Register reg) {528if (VM_Version::arm_arch() >= 7) {529emit_int32(0xF57FF04F);530} else {531bool preserve_tmp = (reg == noreg);532if(preserve_tmp) {533reg = Rtemp;534str(reg, Address(SP, -wordSize, pre_indexed));535}536mov(reg, 0);537// DataSynchronizationBarrier538emit_int32(0xe << 28 |5390xe << 24 |5400x7 << 16 |541reg->encoding() << 12 |5420xf << 8 |5430x9 << 4 |5440xa);545if(preserve_tmp) {546ldr(reg, Address(SP, wordSize, post_indexed));547}548}549}550551552#define F(mnemonic, b) \553void mnemonic(Register rd, Register rm, Register rn, AsmCondition cond = al) { \554assert(rn != rm && rn != rd, "unpredictable instruction"); \555emit_int32(cond << 28 | 0x2 << 23 | b << 22 | rn->encoding() << 16 | \556rd->encoding() << 12 | 9 << 4 | rm->encoding()); \557}558559F(swp, 0)560F(swpb, 1)561#undef F562563// Branches564565#define F(mnemonic, l) \566void mnemonic(Register rm, AsmCondition cond = al) { \567emit_int32(cond << 28 | 0x012fff10 | l << 5 | rm->encoding()); \568}569570F(bx, 0)571F(blx, 1)572#undef F573574#define F(mnemonic, l) \575void mnemonic(address target, AsmCondition cond = al) { \576unsigned int offset = (unsigned int)(target - pc() - 8); \577assert((offset & 3) == 0, "bad alignment"); \578assert((offset >> 25) == 0 || ((int)offset >> 25) == -1, "offset is too large"); \579emit_int32(cond << 28 | l << 24 | offset << 6 >> 8); \580}581582F(b, 0xa)583F(bl, 0xb)584#undef F585586void udf(int imm_16) {587assert((imm_16 >> 16) == 0, "encoding constraint");588emit_int32(0xe7f000f0 | (imm_16 & 0xfff0) << 8 | (imm_16 & 0xf));589}590591// ARMv7 instructions592593#define F(mnemonic, wt) \594void mnemonic(Register rd, int imm_16, AsmCondition cond = al) { \595assert((imm_16 >> 16) == 0, "encoding constraint"); \596emit_int32(cond << 28 | wt << 20 | rd->encoding() << 12 | \597(imm_16 & 0xf000) << 4 | (imm_16 & 0xfff)); \598}599600F(movw, 0x30)601F(movt, 0x34)602#undef F603604// VFP Support605606// Checks that VFP instructions are not used in SOFTFP mode.607#ifdef __SOFTFP__608#define CHECK_VFP_PRESENT ShouldNotReachHere()609#else610#define CHECK_VFP_PRESENT611#endif // __SOFTFP__612613static const int single_cp_num = 0xa00;614static const int double_cp_num = 0xb00;615616// Bits P, Q, R, S collectively form the opcode617#define F(mnemonic, P, Q, R, S) \618void mnemonic##d(FloatRegister fd, FloatRegister fn, FloatRegister fm, \619AsmCondition cond = al) { \620CHECK_VFP_PRESENT; \621assert(fn->lo_bit() == 0 && fd->lo_bit() == 0 && fm->lo_bit() == 0, "single precision register?"); \622emit_int32(cond << 28 | 0x7 << 25 | double_cp_num | \623P << 23 | Q << 21 | R << 20 | S << 6 | \624fn->hi_bits() << 16 | fn->hi_bit() << 7 | \625fd->hi_bits() << 12 | fd->hi_bit() << 22 | \626fm->hi_bits() | fm->hi_bit() << 5); \627} \628void mnemonic##s(FloatRegister fd, FloatRegister fn, FloatRegister fm, \629AsmCondition cond = al) { \630assert(fn->hi_bit() == 0 && fd->hi_bit() == 0 && fm->hi_bit() == 0, "double precision register?"); \631CHECK_VFP_PRESENT; \632emit_int32(cond << 28 | 0x7 << 25 | single_cp_num | \633P << 23 | Q << 21 | R << 20 | S << 6 | \634fn->hi_bits() << 16 | fn->lo_bit() << 7 | \635fd->hi_bits() << 12 | fd->lo_bit() << 22 | \636fm->hi_bits() | fm->lo_bit() << 5); \637}638639F(fmac, 0, 0, 0, 0) // Fd = Fd + (Fn * Fm)640F(fnmac, 0, 0, 0, 1) // Fd = Fd - (Fn * Fm)641F(fmsc, 0, 0, 1, 0) // Fd = -Fd + (Fn * Fm)642F(fnmsc, 0, 0, 1, 1) // Fd = -Fd - (Fn * Fm)643644F(fmul, 0, 1, 0, 0) // Fd = Fn * Fm645F(fnmul, 0, 1, 0, 1) // Fd = -(Fn * Fm)646F(fadd, 0, 1, 1, 0) // Fd = Fn + Fm647F(fsub, 0, 1, 1, 1) // Fd = Fn - Fm648F(fdiv, 1, 0, 0, 0) // Fd = Fn / Fm649#undef F650651enum VElem_Size {652VELEM_SIZE_8 = 0x00,653VELEM_SIZE_16 = 0x01,654VELEM_SIZE_32 = 0x02,655VELEM_SIZE_64 = 0x03656};657658enum VLD_Type {659VLD1_TYPE_1_REG = 0x7 /* 0b0111 */,660VLD1_TYPE_2_REGS = 0xA /* 0b1010 */,661VLD1_TYPE_3_REGS = 0x6 /* 0b0110 */,662VLD1_TYPE_4_REGS = 0x2 /* 0b0010 */663};664665enum VFloat_Arith_Size {666VFA_SIZE_F32 = 0x0 /* 0b0 */,667};668669// Bits P, Q, R, S collectively form the opcode670#define F(mnemonic, P, Q, R, S) \671void mnemonic(FloatRegister fd, FloatRegister fn, FloatRegister fm, \672int size, int quad) { \673CHECK_VFP_PRESENT; \674assert(VM_Version::has_simd(), "simd instruction"); \675assert(fn->lo_bit() == 0 && fd->lo_bit() == 0 && fm->lo_bit() == 0, \676"single precision register?"); \677assert(!quad || ((fn->hi_bits() | fd->hi_bits() | fm->hi_bits()) & 1) == 0, \678"quad precision register?"); \679emit_int32(0xf << 28 | P << 23 | Q << 8 | R << 4 | \680S << 21 | size << 20 | quad << 6 | \681fn->hi_bits() << 16 | fn->hi_bit() << 7 | \682fd->hi_bits() << 12 | fd->hi_bit() << 22 | \683fm->hi_bits() | fm->hi_bit() << 5); \684}685686F(vmulI, 0x4 /* 0b0100 */, 0x9 /* 0b1001 */, 1, 0) // Vd = Vn * Vm (int)687F(vaddI, 0x4 /* 0b0100 */, 0x8 /* 0b1000 */, 0, 0) // Vd = Vn + Vm (int)688F(vsubI, 0x6 /* 0b0110 */, 0x8 /* 0b1000 */, 0, 0) // Vd = Vn - Vm (int)689F(vaddF, 0x4 /* 0b0100 */, 0xD /* 0b1101 */, 0, 0) // Vd = Vn + Vm (float)690F(vsubF, 0x4 /* 0b0100 */, 0xD /* 0b1101 */, 0, 1) // Vd = Vn - Vm (float)691F(vmulF, 0x6 /* 0b0110 */, 0xD /* 0b1101 */, 1, 0) // Vd = Vn * Vm (float)692F(vshlSI, 0x4 /* 0b0100 */, 0x4 /* 0b0100 */, 0, 0) // Vd = ashift(Vm,Vn) (int)693F(vshlUI, 0x6 /* 0b0110 */, 0x4 /* 0b0100 */, 0, 0) // Vd = lshift(Vm,Vn) (int)694F(_vandI, 0x4 /* 0b0100 */, 0x1 /* 0b0001 */, 1, 0) // Vd = Vn & Vm (int)695F(_vorI, 0x4 /* 0b0100 */, 0x1 /* 0b0001 */, 1, 1) // Vd = Vn | Vm (int)696F(_vxorI, 0x6 /* 0b0110 */, 0x1 /* 0b0001 */, 1, 0) // Vd = Vn ^ Vm (int)697#undef F698699void vandI(FloatRegister fd, FloatRegister fn, FloatRegister fm, int quad) {700_vandI(fd, fn, fm, 0, quad);701}702void vorI(FloatRegister fd, FloatRegister fn, FloatRegister fm, int quad) {703_vorI(fd, fn, fm, 0, quad);704}705void vxorI(FloatRegister fd, FloatRegister fn, FloatRegister fm, int quad) {706_vxorI(fd, fn, fm, 0, quad);707}708709void vneg(FloatRegister fd, FloatRegister fm, int size, int flt, int quad) {710CHECK_VFP_PRESENT;711assert(VM_Version::has_simd(), "simd instruction");712assert(fd->lo_bit() == 0 && fm->lo_bit() == 0,713"single precision register?");714assert(!quad || ((fd->hi_bits() | fm->hi_bits()) & 1) == 0,715"quad precision register?");716emit_int32(0xf << 28 | 0x3B /* 0b00111011 */ << 20 | 0x1 /* 0b01 */ << 16 | 0x7 /* 0b111 */ << 7 |717size << 18 | quad << 6 | flt << 10 |718fd->hi_bits() << 12 | fd->hi_bit() << 22 |719fm->hi_bits() << 0 | fm->hi_bit() << 5);720}721722void vnegI(FloatRegister fd, FloatRegister fm, int size, int quad) {723int flt = 0;724vneg(fd, fm, size, flt, quad);725}726727void vshli(FloatRegister fd, FloatRegister fm, int size, int imm, int quad) {728CHECK_VFP_PRESENT;729assert(VM_Version::has_simd(), "simd instruction");730assert(fd->lo_bit() == 0 && fm->lo_bit() == 0,731"single precision register?");732assert(!quad || ((fd->hi_bits() | fm->hi_bits()) & 1) == 0,733"quad precision register?");734735if (imm >= size) {736// maximum shift gives all zeroes, direction doesn't matter,737// but only available for shift right738vshri(fd, fm, size, size, true /* unsigned */, quad);739return;740}741assert(imm >= 0 && imm < size, "out of range");742743int imm6 = 0;744int L = 0;745switch (size) {746case 8:747case 16:748case 32:749imm6 = size + imm ;750break;751case 64:752L = 1;753imm6 = imm ;754break;755default:756ShouldNotReachHere();757}758emit_int32(0xf << 28 | 0x5 /* 0b00101 */ << 23 | 0x51 /* 0b01010001 */ << 4 |759imm6 << 16 | L << 7 | quad << 6 |760fd->hi_bits() << 12 | fd->hi_bit() << 22 |761fm->hi_bits() << 0 | fm->hi_bit() << 5);762}763764void vshri(FloatRegister fd, FloatRegister fm, int size, int imm,765bool U /* unsigned */, int quad) {766CHECK_VFP_PRESENT;767assert(VM_Version::has_simd(), "simd instruction");768assert(fd->lo_bit() == 0 && fm->lo_bit() == 0,769"single precision register?");770assert(!quad || ((fd->hi_bits() | fm->hi_bits()) & 1) == 0,771"quad precision register?");772assert(imm > 0, "out of range");773if (imm >= size) {774// maximum shift (all zeroes)775imm = size;776}777int imm6 = 0;778int L = 0;779switch (size) {780case 8:781case 16:782case 32:783imm6 = 2 * size - imm ;784break;785case 64:786L = 1;787imm6 = 64 - imm ;788break;789default:790ShouldNotReachHere();791}792emit_int32(0xf << 28 | 0x5 /* 0b00101 */ << 23 | 0x1 /* 0b00000001 */ << 4 |793imm6 << 16 | L << 7 | quad << 6 | U << 24 |794fd->hi_bits() << 12 | fd->hi_bit() << 22 |795fm->hi_bits() << 0 | fm->hi_bit() << 5);796}797void vshrUI(FloatRegister fd, FloatRegister fm, int size, int imm, int quad) {798vshri(fd, fm, size, imm, true /* unsigned */, quad);799}800void vshrSI(FloatRegister fd, FloatRegister fm, int size, int imm, int quad) {801vshri(fd, fm, size, imm, false /* signed */, quad);802}803804// Extension opcodes where P,Q,R,S = 1 opcode is in Fn805#define F(mnemonic, N, opcode) \806void mnemonic##d(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \807CHECK_VFP_PRESENT; \808assert(fd->lo_bit() == 0 && fm->hi_bit() == 0, "incorrect register?"); \809emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \810double_cp_num | \811fd->hi_bits() << 12 | fd->hi_bit() << 22 | \812fm->hi_bits() | fm->lo_bit() << 5); \813} \814void mnemonic##s(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \815CHECK_VFP_PRESENT; \816assert(fd->hi_bit() == 0 && fm->hi_bit() == 0, "double precision register?"); \817emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \818single_cp_num | \819fd->hi_bits() << 12 | fd->lo_bit() << 22 | \820fm->hi_bits() | fm->lo_bit() << 5); \821}822823F(fuito, 0, 0x8) // Unsigned integer to floating point conversion824F(fsito, 1, 0x8) // Signed integer to floating point conversion825#undef F826827#define F(mnemonic, N, opcode) \828void mnemonic##d(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \829CHECK_VFP_PRESENT; \830assert(fd->hi_bit() == 0 && fm->lo_bit() == 0, "incorrect register?"); \831emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \832double_cp_num | \833fd->hi_bits() << 12 | fd->lo_bit() << 22 | \834fm->hi_bits() | fm->hi_bit() << 5); \835} \836void mnemonic##s(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \837CHECK_VFP_PRESENT; \838assert(fd->hi_bit() == 0 && fm->hi_bit() == 0, "double precision register?"); \839emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \840single_cp_num | \841fd->hi_bits() << 12 | fd->lo_bit() << 22 | \842fm->hi_bits() | fm->lo_bit() << 5); \843}844845F(ftoui, 0, 0xc) // Float to unsigned int conversion846F(ftouiz, 1, 0xc) // Float to unsigned int conversion, RZ mode847F(ftosi, 0, 0xd) // Float to signed int conversion848F(ftosiz, 1, 0xd) // Float to signed int conversion, RZ mode849#undef F850851#define F(mnemonic, N, opcode) \852void mnemonic##d(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \853CHECK_VFP_PRESENT; \854assert(fd->hi_bit() == 0 && fm->lo_bit() == 0, "incorrect register?"); \855emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \856double_cp_num | \857fd->hi_bits() << 12 | fd->lo_bit() << 22 | \858fm->hi_bits() | fm->hi_bit() << 5); \859} \860void mnemonic##s(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \861CHECK_VFP_PRESENT; \862assert(fd->lo_bit() == 0 && fm->hi_bit() == 0, "incorrect register?"); \863emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \864single_cp_num | \865fd->hi_bits() << 12 | fd->hi_bit() << 22 | \866fm->hi_bits() | fm->lo_bit() << 5); \867}868869F(fcvtd, 1, 0x7) // Single->Double conversion870F(fcvts, 1, 0x7) // Double->Single conversion871#undef F872873#define F(mnemonic, N, opcode) \874void mnemonic##d(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \875CHECK_VFP_PRESENT; \876assert(fd->lo_bit() == 0 && fm->lo_bit() == 0, "single precision register?"); \877emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \878double_cp_num | \879fd->hi_bits() << 12 | fd->hi_bit() << 22 | \880fm->hi_bits() | fm->hi_bit() << 5); \881} \882void mnemonic##s(FloatRegister fd, FloatRegister fm, AsmCondition cond = al) { \883CHECK_VFP_PRESENT; \884assert(fd->hi_bit() == 0 && fm->hi_bit() == 0, "double precision register?"); \885emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \886single_cp_num | \887fd->hi_bits() << 12 | fd->lo_bit() << 22 | \888fm->hi_bits() | fm->lo_bit() << 5); \889}890891F(fcpy, 0, 0x0) // Fd = Fm892F(fabs, 1, 0x0) // Fd = abs(Fm)893F(fneg, 0, 0x1) // Fd = -Fm894F(fsqrt, 1, 0x1) // Fd = sqrt(Fm)895F(fcmp, 0, 0x4) // Compare Fd with Fm no exceptions on quiet NANs896F(fcmpe, 1, 0x4) // Compare Fd with Fm with exceptions on quiet NANs897#undef F898899// Opcodes with one operand only900#define F(mnemonic, N, opcode) \901void mnemonic##d(FloatRegister fd, AsmCondition cond = al) { \902CHECK_VFP_PRESENT; \903assert(fd->lo_bit() == 0, "single precision register?"); \904emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \905double_cp_num | fd->hi_bits() << 12 | fd->hi_bit() << 22); \906} \907void mnemonic##s(FloatRegister fd, AsmCondition cond = al) { \908CHECK_VFP_PRESENT; \909assert(fd->hi_bit() == 0, "double precision register?"); \910emit_int32(cond << 28 | 0xeb << 20 | opcode << 16 | N << 7 | 1 << 6 | \911single_cp_num | fd->hi_bits() << 12 | fd->lo_bit() << 22); \912}913914F(fcmpz, 0, 0x5) // Compare Fd with 0, no exceptions quiet NANs915F(fcmpez, 1, 0x5) // Compare Fd with 0, with exceptions quiet NANs916#undef F917918// Float loads (L==1) and stores (L==0)919#define F(mnemonic, L) \920void mnemonic##d(FloatRegister fd, Address addr, AsmCondition cond = al) { \921CHECK_VFP_PRESENT; \922assert(fd->lo_bit() == 0, "single precision register?"); \923emit_int32(cond << 28 | 0xd << 24 | L << 20 | \924fd->hi_bits() << 12 | fd->hi_bit() << 22 | \925double_cp_num | addr.encoding_vfp()); \926} \927void mnemonic##s(FloatRegister fd, Address addr, AsmCondition cond = al) { \928CHECK_VFP_PRESENT; \929assert(fd->hi_bit() == 0, "double precision register?"); \930emit_int32(cond << 28 | 0xd << 24 | L << 20 | \931fd->hi_bits() << 12 | fd->lo_bit() << 22 | \932single_cp_num | addr.encoding_vfp()); \933}934935F(fst, 0) // Store 1 register936F(fld, 1) // Load 1 register937#undef F938939// Float load and store multiple940#define F(mnemonic, l, pu) \941void mnemonic##d(Register rn, FloatRegisterSet reg_set, \942AsmWriteback w = no_writeback, AsmCondition cond = al) { \943CHECK_VFP_PRESENT; \944assert(w == no_writeback || rn != PC, "unpredictable instruction"); \945assert(!(w == no_writeback && pu == 2), "encoding constraint"); \946assert((reg_set.encoding_d() & 1) == 0, "encoding constraint"); \947emit_int32(cond << 28 | 6 << 25 | pu << 23 | w << 21 | l << 20 | \948rn->encoding() << 16 | reg_set.encoding_d() | double_cp_num); \949} \950void mnemonic##s(Register rn, FloatRegisterSet reg_set, \951AsmWriteback w = no_writeback, AsmCondition cond = al) { \952CHECK_VFP_PRESENT; \953assert(w == no_writeback || rn != PC, "unpredictable instruction"); \954assert(!(w == no_writeback && pu == 2), "encoding constraint"); \955emit_int32(cond << 28 | 6 << 25 | pu << 23 | w << 21 | l << 20 | \956rn->encoding() << 16 | reg_set.encoding_s() | single_cp_num); \957}958959F(fldmia, 1, 1) F(fldmfd, 1, 1)960F(fldmdb, 1, 2) F(fldmea, 1, 2)961F(fstmia, 0, 1) F(fstmea, 0, 1)962F(fstmdb, 0, 2) F(fstmfd, 0, 2)963#undef F964965// fconst{s,d} encoding:966// 31 28 27 23 22 21 20 19 16 15 12 10 9 8 7 4 3 0967// | cond | 11101 | D | 11 | imm4H | Vd | 101 | sz | 0000 | imm4L |968// sz = 0 for single precision, 1 otherwise969// Register number is Vd:D for single precision, D:Vd otherwise970// immediate value is imm4H:imm4L971972void fconsts(FloatRegister fd, unsigned char imm_8, AsmCondition cond = al) {973CHECK_VFP_PRESENT;974assert(fd->hi_bit() == 0, "double precision register?");975emit_int32(cond << 28 | 0xeb << 20 | single_cp_num |976fd->hi_bits() << 12 | fd->lo_bit() << 22 | (imm_8 & 0xf) | (imm_8 >> 4) << 16);977}978979void fconstd(FloatRegister fd, unsigned char imm_8, AsmCondition cond = al) {980CHECK_VFP_PRESENT;981assert(fd->lo_bit() == 0, "double precision register?");982emit_int32(cond << 28 | 0xeb << 20 | double_cp_num |983fd->hi_bits() << 12 | fd->hi_bit() << 22 | (imm_8 & 0xf) | (imm_8 >> 4) << 16);984}985986// GPR <-> FPR transfers987void fmsr(FloatRegister fd, Register rd, AsmCondition cond = al) {988CHECK_VFP_PRESENT;989assert(fd->hi_bit() == 0, "double precision register?");990emit_int32(cond << 28 | 0xe0 << 20 | single_cp_num | 1 << 4 |991fd->hi_bits() << 16 | fd->lo_bit() << 7 | rd->encoding() << 12);992}993994void fmrs(Register rd, FloatRegister fd, AsmCondition cond = al) {995CHECK_VFP_PRESENT;996assert(fd->hi_bit() == 0, "double precision register?");997emit_int32(cond << 28 | 0xe1 << 20 | single_cp_num | 1 << 4 |998fd->hi_bits() << 16 | fd->lo_bit() << 7 | rd->encoding() << 12);999}10001001void fmdrr(FloatRegister fd, Register rd, Register rn, AsmCondition cond = al) {1002CHECK_VFP_PRESENT;1003assert(fd->lo_bit() == 0, "single precision register?");1004emit_int32(cond << 28 | 0xc4 << 20 | double_cp_num | 1 << 4 |1005fd->hi_bits() | fd->hi_bit() << 5 |1006rn->encoding() << 16 | rd->encoding() << 12);1007}10081009void fmrrd(Register rd, Register rn, FloatRegister fd, AsmCondition cond = al) {1010CHECK_VFP_PRESENT;1011assert(fd->lo_bit() == 0, "single precision register?");1012emit_int32(cond << 28 | 0xc5 << 20 | double_cp_num | 1 << 4 |1013fd->hi_bits() | fd->hi_bit() << 5 |1014rn->encoding() << 16 | rd->encoding() << 12);1015}10161017void fmstat(AsmCondition cond = al) {1018CHECK_VFP_PRESENT;1019emit_int32(cond << 28 | 0xef1fa10);1020}10211022void vmrs(Register rt, VFPSystemRegister sr, AsmCondition cond = al) {1023assert((sr->encoding() & (~0xf)) == 0, "what system register is that?");1024emit_int32(cond << 28 | rt->encoding() << 12 | sr->encoding() << 16 | 0xef00a10);1025}10261027void vmsr(VFPSystemRegister sr, Register rt, AsmCondition cond = al) {1028assert((sr->encoding() & (~0xf)) == 0, "what system register is that?");1029emit_int32(cond << 28 | rt->encoding() << 12 | sr->encoding() << 16 | 0xee00a10);1030}10311032void vcnt(FloatRegister Dd, FloatRegister Dm) {1033CHECK_VFP_PRESENT;1034// emitted at VM startup to detect whether the instruction is available1035assert(!VM_Version::is_initialized() || VM_Version::has_simd(), "simd instruction");1036assert(Dd->lo_bit() == 0 && Dm->lo_bit() == 0, "single precision registers?");1037emit_int32(0xf3b00500 | Dd->hi_bit() << 22 | Dd->hi_bits() << 12 | Dm->hi_bit() << 5 | Dm->hi_bits());1038}10391040void vpaddl(FloatRegister Dd, FloatRegister Dm, int size, bool s) {1041CHECK_VFP_PRESENT;1042assert(VM_Version::has_simd(), "simd instruction");1043assert(Dd->lo_bit() == 0 && Dm->lo_bit() == 0, "single precision registers?");1044assert(size == 8 || size == 16 || size == 32, "unexpected size");1045emit_int32(0xf3b00200 | Dd->hi_bit() << 22 | (size >> 4) << 18 | Dd->hi_bits() << 12 | (s ? 0 : 1) << 7 | Dm->hi_bit() << 5 | Dm->hi_bits());1046}10471048void vld1(FloatRegister Dd, Address addr, VElem_Size size, int bits) {1049CHECK_VFP_PRESENT;1050assert(VM_Version::has_simd(), "simd instruction");1051assert(Dd->lo_bit() == 0, "single precision registers?");1052int align = 0;1053assert(bits == 128, "code assumption");1054VLD_Type type = VLD1_TYPE_2_REGS; // 2x641055emit_int32(0xf4200000 | Dd->hi_bit() << 22 | Dd->hi_bits() << 12 | type << 8 | size << 6 | align << 4 | addr.encoding_simd());1056}10571058void vst1(FloatRegister Dd, Address addr, VElem_Size size, int bits) {1059CHECK_VFP_PRESENT;1060assert(VM_Version::has_simd(), "simd instruction");1061assert(Dd->lo_bit() == 0, "single precision registers?");1062int align = 0;1063assert(bits == 128, "code assumption");1064VLD_Type type = VLD1_TYPE_2_REGS; // 2x641065emit_int32(0xf4000000 | Dd->hi_bit() << 22 | Dd->hi_bits() << 12 | type << 8 | size << 6 | align << 4 | addr.encoding_simd());1066}10671068void vmovI(FloatRegister Dd, int imm8, VElem_Size size, int quad) {1069CHECK_VFP_PRESENT;1070assert(VM_Version::has_simd(), "simd instruction");1071assert(Dd->lo_bit() == 0, "single precision register?");1072assert(!quad || (Dd->hi_bits() & 1) == 0, "quad precision register?");1073assert(imm8 >= 0 && imm8 < 256, "out of range");1074int op;1075int cmode;1076switch (size) {1077case VELEM_SIZE_8:1078op = 0;1079cmode = 0xE /* 0b1110 */;1080break;1081case VELEM_SIZE_16:1082op = 0;1083cmode = 0x8 /* 0b1000 */;1084break;1085case VELEM_SIZE_32:1086op = 0;1087cmode = 0x0 /* 0b0000 */;1088break;1089default:1090ShouldNotReachHere();1091return;1092}1093emit_int32(0xf << 28 | 0x1 << 25 | 0x1 << 23 | 0x1 << 4 |1094(imm8 >> 7) << 24 | ((imm8 & 0x70) >> 4) << 16 | (imm8 & 0xf) |1095quad << 6 | op << 5 | cmode << 8 |1096Dd->hi_bits() << 12 | Dd->hi_bit() << 22);1097}10981099void vdupI(FloatRegister Dd, Register Rs, VElem_Size size, int quad,1100AsmCondition cond = al) {1101CHECK_VFP_PRESENT;1102assert(VM_Version::has_simd(), "simd instruction");1103assert(Dd->lo_bit() == 0, "single precision register?");1104assert(!quad || (Dd->hi_bits() & 1) == 0, "quad precision register?");1105int b;1106int e;1107switch (size) {1108case VELEM_SIZE_8:1109b = 1;1110e = 0;1111break;1112case VELEM_SIZE_16:1113b = 0;1114e = 1;1115break;1116case VELEM_SIZE_32:1117b = 0;1118e = 0;1119break;1120default:1121ShouldNotReachHere();1122return;1123}1124emit_int32(cond << 28 | 0x1D /* 0b11101 */ << 23 | 0xB /* 0b1011 */ << 8 | 0x1 << 4 |1125quad << 21 | b << 22 | e << 5 | Rs->encoding() << 12 |1126Dd->hi_bits() << 16 | Dd->hi_bit() << 7);1127}11281129void vdup(FloatRegister Dd, FloatRegister Ds, int index, int size, int quad) {1130CHECK_VFP_PRESENT;1131assert(VM_Version::has_simd(), "simd instruction");1132assert(Dd->lo_bit() == 0, "single precision register?");1133assert(Ds->lo_bit() == 0, "single precision register?");1134assert(!quad || (Dd->hi_bits() & 1) == 0, "quad precision register?");1135int range = 64 / size;1136assert(index < range, "overflow");1137int imm4;1138switch (size) {1139case 8:1140assert((index & 0x7 /* 0b111 */) == index, "overflow");1141imm4 = index << 1 | 0x1 /* 0b0001 */;1142break;1143case 16:1144assert((index & 0x3 /* 0b11 */) == index, "overflow");1145imm4 = index << 2 | 0x2 /* 0b0010 */;1146break;1147case 32:1148assert((index & 0x1 /* 0b1 */) == index, "overflow");1149imm4 = index << 3 | 0x4 /* 0b0100 */;1150break;1151default:1152ShouldNotReachHere();1153return;1154}1155emit_int32(0xF /* 0b1111 */ << 28 | 0x3B /* 0b00111011 */ << 20 | 0x6 /* 0b110 */ << 9 |1156quad << 6 | imm4 << 16 |1157Dd->hi_bits() << 12 | Dd->hi_bit() << 22 |1158Ds->hi_bits() << 00 | Ds->hi_bit() << 5);1159}11601161void vdupF(FloatRegister Dd, FloatRegister Ss, int quad) {1162int index = 0;1163FloatRegister Ds = as_FloatRegister(Ss->encoding() & ~1);1164if (Ss->lo_bit() != 0) {1165/* odd S register */1166assert(Ds->successor() == Ss, "bad reg");1167index = 1;1168} else {1169/* even S register */1170assert(Ds == Ss, "bad reg");1171}1172vdup(Dd, Ds, index, 32, quad);1173}11741175void vrev(FloatRegister Dd, FloatRegister Dm, int quad, int region_size, VElem_Size size) {1176CHECK_VFP_PRESENT;1177assert(VM_Version::has_simd(), "simd instruction");1178assert(Dd->lo_bit() == 0, "single precision register?");1179assert(Dm->lo_bit() == 0, "single precision register?");1180assert(!quad || ((Dd->hi_bits() | Dm->hi_bits()) & 1) == 0,1181"quad precision register?");1182unsigned int op = 0;1183switch (region_size) {1184case 16: op = 0x2; /*0b10*/ break;1185case 32: op = 0x1; /*0b01*/ break;1186case 64: op = 0x0; /*0b00*/ break;1187default: assert(false, "encoding constraint");1188}1189emit_int32(0xf << 28 | 0x7 << 23 | Dd->hi_bit() << 22 | 0x3 << 20 |1190size << 18 | Dd->hi_bits() << 12 | op << 7 | quad << 6 | Dm->hi_bit() << 5 |1191Dm->hi_bits());1192}11931194void veor(FloatRegister Dd, FloatRegister Dn, FloatRegister Dm, int quad) {1195CHECK_VFP_PRESENT;1196assert(VM_Version::has_simd(), "simd instruction");1197assert(Dd->lo_bit() == 0, "single precision register?");1198assert(Dm->lo_bit() == 0, "single precision register?");1199assert(Dn->lo_bit() == 0, "single precision register?");1200assert(!quad || ((Dd->hi_bits() | Dm->hi_bits() | Dn->hi_bits()) & 1) == 0,1201"quad precision register?");12021203emit_int32(0xf << 28 | 0x3 << 24 | Dd->hi_bit() << 22 | Dn->hi_bits() << 16 |1204Dd->hi_bits() << 12 | 0x1 << 8 | Dn->hi_bit() << 7 | quad << 6 |1205Dm->hi_bit() << 5 | 0x1 << 4 | Dm->hi_bits());1206}120712081209Assembler(CodeBuffer* code) : AbstractAssembler(code) {}12101211#ifdef COMPILER21212typedef VFP::double_num double_num;1213typedef VFP::float_num float_num;1214#endif1215};12161217#ifdef __SOFTFP__1218// Soft float function declarations1219extern "C" {1220extern float __aeabi_fadd(float, float);1221extern float __aeabi_fmul(float, float);1222extern float __aeabi_fsub(float, float);1223extern float __aeabi_fdiv(float, float);12241225extern double __aeabi_dadd(double, double);1226extern double __aeabi_dmul(double, double);1227extern double __aeabi_dsub(double, double);1228extern double __aeabi_ddiv(double, double);12291230extern double __aeabi_f2d(float);1231extern float __aeabi_d2f(double);1232extern float __aeabi_i2f(int);1233extern double __aeabi_i2d(int);1234extern int __aeabi_f2iz(float);12351236extern int __aeabi_fcmpeq(float, float);1237extern int __aeabi_fcmplt(float, float);1238extern int __aeabi_fcmple(float, float);1239extern int __aeabi_fcmpge(float, float);1240extern int __aeabi_fcmpgt(float, float);12411242extern int __aeabi_dcmpeq(double, double);1243extern int __aeabi_dcmplt(double, double);1244extern int __aeabi_dcmple(double, double);1245extern int __aeabi_dcmpge(double, double);1246extern int __aeabi_dcmpgt(double, double);12471248// Imported code from glibc soft-fp bundle for1249// calculation accuracy improvement. See CR 6757269.1250extern double __aeabi_fadd_glibc(float, float);1251extern double __aeabi_fsub_glibc(float, float);1252extern double __aeabi_dadd_glibc(double, double);1253extern double __aeabi_dsub_glibc(double, double);1254};1255#endif // __SOFTFP__125612571258#endif // CPU_ARM_ASSEMBLER_ARM_32_HPP125912601261