Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp
32285 views
/*1* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.2* Copyright (c) 2013, 2019, Red Hat Inc. 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 it6* under the terms of the GNU General Public License version 2 only, as7* published by the Free Software Foundation.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 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 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*23*/2425#ifndef CPU_AARCH64_VM_ASSEMBLER_AARCH64_HPP26#define CPU_AARCH64_VM_ASSEMBLER_AARCH64_HPP2728#include "asm/register.hpp"2930// definitions of various symbolic names for machine registers3132// First intercalls between C and Java which use 8 general registers33// and 8 floating registers3435// we also have to copy between x86 and ARM registers but that's a36// secondary complication -- not all code employing C call convention37// executes as x86 code though -- we generate some of it3839class Argument VALUE_OBJ_CLASS_SPEC {40public:41enum {42n_int_register_parameters_c = 8, // r0, r1, ... r7 (c_rarg0, c_rarg1, ...)43n_float_register_parameters_c = 8, // v0, v1, ... v7 (c_farg0, c_farg1, ... )4445n_int_register_parameters_j = 8, // r1, ... r7, r0 (rj_rarg0, j_rarg1, ...46n_float_register_parameters_j = 8 // v0, v1, ... v7 (j_farg0, j_farg1, ...47};48};4950REGISTER_DECLARATION(Register, c_rarg0, r0);51REGISTER_DECLARATION(Register, c_rarg1, r1);52REGISTER_DECLARATION(Register, c_rarg2, r2);53REGISTER_DECLARATION(Register, c_rarg3, r3);54REGISTER_DECLARATION(Register, c_rarg4, r4);55REGISTER_DECLARATION(Register, c_rarg5, r5);56REGISTER_DECLARATION(Register, c_rarg6, r6);57REGISTER_DECLARATION(Register, c_rarg7, r7);5859REGISTER_DECLARATION(FloatRegister, c_farg0, v0);60REGISTER_DECLARATION(FloatRegister, c_farg1, v1);61REGISTER_DECLARATION(FloatRegister, c_farg2, v2);62REGISTER_DECLARATION(FloatRegister, c_farg3, v3);63REGISTER_DECLARATION(FloatRegister, c_farg4, v4);64REGISTER_DECLARATION(FloatRegister, c_farg5, v5);65REGISTER_DECLARATION(FloatRegister, c_farg6, v6);66REGISTER_DECLARATION(FloatRegister, c_farg7, v7);6768// Symbolically name the register arguments used by the Java calling convention.69// We have control over the convention for java so we can do what we please.70// What pleases us is to offset the java calling convention so that when71// we call a suitable jni method the arguments are lined up and we don't72// have to do much shuffling. A suitable jni method is non-static and a73// small number of arguments74//75// |--------------------------------------------------------------------|76// | c_rarg0 c_rarg1 c_rarg2 c_rarg3 c_rarg4 c_rarg5 c_rarg6 c_rarg7 |77// |--------------------------------------------------------------------|78// | r0 r1 r2 r3 r4 r5 r6 r7 |79// |--------------------------------------------------------------------|80// | j_rarg7 j_rarg0 j_rarg1 j_rarg2 j_rarg3 j_rarg4 j_rarg5 j_rarg6 |81// |--------------------------------------------------------------------|828384REGISTER_DECLARATION(Register, j_rarg0, c_rarg1);85REGISTER_DECLARATION(Register, j_rarg1, c_rarg2);86REGISTER_DECLARATION(Register, j_rarg2, c_rarg3);87REGISTER_DECLARATION(Register, j_rarg3, c_rarg4);88REGISTER_DECLARATION(Register, j_rarg4, c_rarg5);89REGISTER_DECLARATION(Register, j_rarg5, c_rarg6);90REGISTER_DECLARATION(Register, j_rarg6, c_rarg7);91REGISTER_DECLARATION(Register, j_rarg7, c_rarg0);9293// Java floating args are passed as per C9495REGISTER_DECLARATION(FloatRegister, j_farg0, v0);96REGISTER_DECLARATION(FloatRegister, j_farg1, v1);97REGISTER_DECLARATION(FloatRegister, j_farg2, v2);98REGISTER_DECLARATION(FloatRegister, j_farg3, v3);99REGISTER_DECLARATION(FloatRegister, j_farg4, v4);100REGISTER_DECLARATION(FloatRegister, j_farg5, v5);101REGISTER_DECLARATION(FloatRegister, j_farg6, v6);102REGISTER_DECLARATION(FloatRegister, j_farg7, v7);103104// registers used to hold VM data either temporarily within a method105// or across method calls106107// volatile (caller-save) registers108109// r8 is used for indirect result location return110// we use it and r9 as scratch registers111REGISTER_DECLARATION(Register, rscratch1, r8);112REGISTER_DECLARATION(Register, rscratch2, r9);113114// current method -- must be in a call-clobbered register115REGISTER_DECLARATION(Register, rmethod, r12);116117// non-volatile (callee-save) registers are r16-29118// of which the following are dedicated global state119120// link register121REGISTER_DECLARATION(Register, lr, r30);122// frame pointer123REGISTER_DECLARATION(Register, rfp, r29);124// current thread125REGISTER_DECLARATION(Register, rthread, r28);126// base of heap127REGISTER_DECLARATION(Register, rheapbase, r27);128// constant pool cache129REGISTER_DECLARATION(Register, rcpool, r26);130// monitors allocated on stack131REGISTER_DECLARATION(Register, rmonitors, r25);132// locals on stack133REGISTER_DECLARATION(Register, rlocals, r24);134// bytecode pointer135REGISTER_DECLARATION(Register, rbcp, r22);136// Dispatch table base137REGISTER_DECLARATION(Register, rdispatch, r21);138// Java stack pointer139REGISTER_DECLARATION(Register, esp, r20);140141// TODO : x86 uses rbp to save SP in method handle code142// we may need to do the same with fp143// JSR 292 fixed register usages:144//REGISTER_DECLARATION(Register, r_mh_SP_save, r29);145146#define assert_cond(ARG1) assert(ARG1, #ARG1)147148namespace asm_util {149uint32_t encode_logical_immediate(bool is32, uint64_t imm);150};151152using namespace asm_util;153154155class Assembler;156157class Instruction_aarch64 {158unsigned insn;159#ifdef ASSERT160unsigned bits;161#endif162Assembler *assem;163164public:165166Instruction_aarch64(class Assembler *as) {167#ifdef ASSERT168bits = 0;169#endif170insn = 0;171assem = as;172}173174inline ~Instruction_aarch64();175176unsigned &get_insn() { return insn; }177#ifdef ASSERT178unsigned &get_bits() { return bits; }179#endif180181static inline int32_t extend(unsigned val, int hi = 31, int lo = 0) {182union {183unsigned u;184int n;185};186187u = val << (31 - hi);188n = n >> (31 - hi + lo);189return n;190}191192static inline uint32_t extract(uint32_t val, int msb, int lsb) {193int nbits = msb - lsb + 1;194assert_cond(msb >= lsb);195uint32_t mask = (1U << nbits) - 1;196uint32_t result = val >> lsb;197result &= mask;198return result;199}200201static inline int32_t sextract(uint32_t val, int msb, int lsb) {202uint32_t uval = extract(val, msb, lsb);203return extend(uval, msb - lsb);204}205206static void patch(address a, int msb, int lsb, unsigned long val) {207int nbits = msb - lsb + 1;208guarantee(val < (1U << nbits), "Field too big for insn");209assert_cond(msb >= lsb);210unsigned mask = (1U << nbits) - 1;211val <<= lsb;212mask <<= lsb;213unsigned target = *(unsigned *)a;214target &= ~mask;215target |= val;216*(unsigned *)a = target;217}218219static void spatch(address a, int msb, int lsb, long val) {220int nbits = msb - lsb + 1;221long chk = val >> (nbits - 1);222guarantee (chk == -1 || chk == 0, "Field too big for insn");223unsigned uval = val;224unsigned mask = (1U << nbits) - 1;225uval &= mask;226uval <<= lsb;227mask <<= lsb;228unsigned target = *(unsigned *)a;229target &= ~mask;230target |= uval;231*(unsigned *)a = target;232}233234void f(unsigned val, int msb, int lsb) {235int nbits = msb - lsb + 1;236guarantee(val < (1U << nbits), "Field too big for insn");237assert_cond(msb >= lsb);238unsigned mask = (1U << nbits) - 1;239val <<= lsb;240mask <<= lsb;241insn |= val;242assert_cond((bits & mask) == 0);243#ifdef ASSERT244bits |= mask;245#endif246}247248void f(unsigned val, int bit) {249f(val, bit, bit);250}251252void sf(long val, int msb, int lsb) {253int nbits = msb - lsb + 1;254long chk = val >> (nbits - 1);255guarantee (chk == -1 || chk == 0, "Field too big for insn");256unsigned uval = val;257unsigned mask = (1U << nbits) - 1;258uval &= mask;259f(uval, lsb + nbits - 1, lsb);260}261262void rf(Register r, int lsb) {263f(r->encoding_nocheck(), lsb + 4, lsb);264}265266// reg|ZR267void zrf(Register r, int lsb) {268f(r->encoding_nocheck() - (r == zr), lsb + 4, lsb);269}270271// reg|SP272void srf(Register r, int lsb) {273f(r == sp ? 31 : r->encoding_nocheck(), lsb + 4, lsb);274}275276void rf(FloatRegister r, int lsb) {277f(r->encoding_nocheck(), lsb + 4, lsb);278}279280unsigned get(int msb = 31, int lsb = 0) {281int nbits = msb - lsb + 1;282unsigned mask = ((1U << nbits) - 1) << lsb;283assert_cond((bits & mask) == mask);284return (insn & mask) >> lsb;285}286287void fixed(unsigned value, unsigned mask) {288assert_cond ((mask & bits) == 0);289#ifdef ASSERT290bits |= mask;291#endif292insn |= value;293}294};295296#define starti Instruction_aarch64 do_not_use(this); set_current(&do_not_use)297298class PrePost {299int _offset;300Register _r;301public:302PrePost(Register reg, int o) : _r(reg), _offset(o) { }303int offset() { return _offset; }304Register reg() { return _r; }305};306307class Pre : public PrePost {308public:309Pre(Register reg, int o) : PrePost(reg, o) { }310};311class Post : public PrePost {312public:313Post(Register reg, int o) : PrePost(reg, o) { }314};315316namespace ext317{318enum operation { uxtb, uxth, uxtw, uxtx, sxtb, sxth, sxtw, sxtx };319};320321// Addressing modes322class Address VALUE_OBJ_CLASS_SPEC {323public:324325enum mode { no_mode, base_plus_offset, pre, post, pcrel,326base_plus_offset_reg, literal };327328// Shift and extend for base reg + reg offset addressing329class extend {330int _option, _shift;331ext::operation _op;332public:333extend() { }334extend(int s, int o, ext::operation op) : _shift(s), _option(o), _op(op) { }335int option() const{ return _option; }336int shift() const { return _shift; }337ext::operation op() const { return _op; }338};339class uxtw : public extend {340public:341uxtw(int shift = -1): extend(shift, 0b010, ext::uxtw) { }342};343class lsl : public extend {344public:345lsl(int shift = -1): extend(shift, 0b011, ext::uxtx) { }346};347class sxtw : public extend {348public:349sxtw(int shift = -1): extend(shift, 0b110, ext::sxtw) { }350};351class sxtx : public extend {352public:353sxtx(int shift = -1): extend(shift, 0b111, ext::sxtx) { }354};355356private:357Register _base;358Register _index;359long _offset;360enum mode _mode;361extend _ext;362363RelocationHolder _rspec;364365// Typically we use AddressLiterals we want to use their rval366// However in some situations we want the lval (effect address) of367// the item. We provide a special factory for making those lvals.368bool _is_lval;369370// If the target is far we'll need to load the ea of this to a371// register to reach it. Otherwise if near we can do PC-relative372// addressing.373address _target;374375public:376Address()377: _mode(no_mode) { }378Address(Register r)379: _mode(base_plus_offset), _base(r), _offset(0), _index(noreg), _target(0) { }380Address(Register r, int o)381: _mode(base_plus_offset), _base(r), _offset(o), _index(noreg), _target(0) { }382Address(Register r, long o)383: _mode(base_plus_offset), _base(r), _offset(o), _index(noreg), _target(0) { }384Address(Register r, unsigned long o)385: _mode(base_plus_offset), _base(r), _offset(o), _index(noreg), _target(0) { }386#ifdef ASSERT387Address(Register r, ByteSize disp)388: _mode(base_plus_offset), _base(r), _offset(in_bytes(disp)),389_index(noreg), _target(0) { }390#endif391Address(Register r, Register r1, extend ext = lsl())392: _mode(base_plus_offset_reg), _base(r), _index(r1),393_ext(ext), _offset(0), _target(0) { }394Address(Pre p)395: _mode(pre), _base(p.reg()), _offset(p.offset()) { }396Address(Post p)397: _mode(post), _base(p.reg()), _offset(p.offset()), _target(0) { }398Address(address target, RelocationHolder const& rspec)399: _mode(literal),400_rspec(rspec),401_is_lval(false),402_target(target) { }403Address(address target, relocInfo::relocType rtype = relocInfo::external_word_type);404Address(Register base, RegisterOrConstant index, extend ext = lsl())405: _base (base),406_ext(ext), _offset(0), _target(0) {407if (index.is_register()) {408_mode = base_plus_offset_reg;409_index = index.as_register();410} else {411guarantee(ext.option() == ext::uxtx, "should be");412assert(index.is_constant(), "should be");413_mode = base_plus_offset;414_offset = index.as_constant() << ext.shift();415}416}417418Register base() const {419guarantee((_mode == base_plus_offset | _mode == base_plus_offset_reg420| _mode == post),421"wrong mode");422return _base;423}424long offset() const {425return _offset;426}427Register index() const {428return _index;429}430mode getMode() const {431return _mode;432}433bool uses(Register reg) const { return _base == reg || _index == reg; }434address target() const { return _target; }435const RelocationHolder& rspec() const { return _rspec; }436437void encode(Instruction_aarch64 *i) const {438i->f(0b111, 29, 27);439i->srf(_base, 5);440441switch(_mode) {442case base_plus_offset:443{444unsigned size = i->get(31, 30);445if (i->get(26, 26) && i->get(23, 23)) {446// SIMD Q Type - Size = 128 bits447assert(size == 0, "bad size");448size = 0b100;449}450unsigned mask = (1 << size) - 1;451if (_offset < 0 || _offset & mask)452{453i->f(0b00, 25, 24);454i->f(0, 21), i->f(0b00, 11, 10);455i->sf(_offset, 20, 12);456} else {457i->f(0b01, 25, 24);458i->f(_offset >> size, 21, 10);459}460}461break;462463case base_plus_offset_reg:464{465i->f(0b00, 25, 24);466i->f(1, 21);467i->rf(_index, 16);468i->f(_ext.option(), 15, 13);469unsigned size = i->get(31, 30);470if (i->get(26, 26) && i->get(23, 23)) {471// SIMD Q Type - Size = 128 bits472assert(size == 0, "bad size");473size = 0b100;474}475if (size == 0) // It's a byte476i->f(_ext.shift() >= 0, 12);477else {478if (_ext.shift() > 0)479assert(_ext.shift() == (int)size, "bad shift");480i->f(_ext.shift() > 0, 12);481}482i->f(0b10, 11, 10);483}484break;485486case pre:487i->f(0b00, 25, 24);488i->f(0, 21), i->f(0b11, 11, 10);489i->sf(_offset, 20, 12);490break;491492case post:493i->f(0b00, 25, 24);494i->f(0, 21), i->f(0b01, 11, 10);495i->sf(_offset, 20, 12);496break;497498default:499ShouldNotReachHere();500}501}502503void encode_pair(Instruction_aarch64 *i) const {504switch(_mode) {505case base_plus_offset:506i->f(0b010, 25, 23);507break;508case pre:509i->f(0b011, 25, 23);510break;511case post:512i->f(0b001, 25, 23);513break;514default:515ShouldNotReachHere();516}517518unsigned size; // Operand shift in 32-bit words519520if (i->get(26, 26)) { // float521switch(i->get(31, 30)) {522case 0b10:523size = 2; break;524case 0b01:525size = 1; break;526case 0b00:527size = 0; break;528default:529ShouldNotReachHere();530}531} else {532size = i->get(31, 31);533}534535size = 4 << size;536guarantee(_offset % size == 0, "bad offset");537i->sf(_offset / size, 21, 15);538i->srf(_base, 5);539}540541void encode_nontemporal_pair(Instruction_aarch64 *i) const {542// Only base + offset is allowed543i->f(0b000, 25, 23);544unsigned size = i->get(31, 31);545size = 4 << size;546guarantee(_offset % size == 0, "bad offset");547i->sf(_offset / size, 21, 15);548i->srf(_base, 5);549guarantee(_mode == Address::base_plus_offset,550"Bad addressing mode for non-temporal op");551}552553void lea(MacroAssembler *, Register) const;554555static bool offset_ok_for_immed(long offset, int shift = 0) {556unsigned mask = (1 << shift) - 1;557if (offset < 0 || offset & mask) {558return (uabs(offset) < (1 << (20 - 12))); // Unscaled offset559} else {560return ((offset >> shift) < (1 << (21 - 10 + 1))); // Scaled, unsigned offset561}562}563};564565// Convience classes566class RuntimeAddress: public Address {567568public:569570RuntimeAddress(address target) : Address(target, relocInfo::runtime_call_type) {}571572};573574class OopAddress: public Address {575576public:577578OopAddress(address target) : Address(target, relocInfo::oop_type){}579580};581582class ExternalAddress: public Address {583private:584static relocInfo::relocType reloc_for_target(address target) {585// Sometimes ExternalAddress is used for values which aren't586// exactly addresses, like the card table base.587// external_word_type can't be used for values in the first page588// so just skip the reloc in that case.589return external_word_Relocation::can_be_relocated(target) ? relocInfo::external_word_type : relocInfo::none;590}591592public:593594ExternalAddress(address target) : Address(target, reloc_for_target(target)) {}595596};597598class InternalAddress: public Address {599600public:601602InternalAddress(address target) : Address(target, relocInfo::internal_word_type) {}603};604605const int FPUStateSizeInWords = 32 * 2;606typedef enum {607PLDL1KEEP = 0b00000, PLDL1STRM, PLDL2KEEP, PLDL2STRM, PLDL3KEEP, PLDL3STRM,608PSTL1KEEP = 0b10000, PSTL1STRM, PSTL2KEEP, PSTL2STRM, PSTL3KEEP, PSTL3STRM,609PLIL1KEEP = 0b01000, PLIL1STRM, PLIL2KEEP, PLIL2STRM, PLIL3KEEP, PLIL3STRM610} prfop;611612class Assembler : public AbstractAssembler {613614#ifndef PRODUCT615static const unsigned long asm_bp;616617void emit_long(jint x) {618if ((unsigned long)pc() == asm_bp)619asm volatile ("nop");620AbstractAssembler::emit_int32(x);621}622#else623void emit_long(jint x) {624AbstractAssembler::emit_int32(x);625}626#endif627628public:629630enum { instruction_size = 4 };631632Address adjust(Register base, int offset, bool preIncrement) {633if (preIncrement)634return Address(Pre(base, offset));635else636return Address(Post(base, offset));637}638639Address pre(Register base, int offset) {640return adjust(base, offset, true);641}642643Address post (Register base, int offset) {644return adjust(base, offset, false);645}646647Instruction_aarch64* current;648649void set_current(Instruction_aarch64* i) { current = i; }650651void f(unsigned val, int msb, int lsb) {652current->f(val, msb, lsb);653}654void f(unsigned val, int msb) {655current->f(val, msb, msb);656}657void sf(long val, int msb, int lsb) {658current->sf(val, msb, lsb);659}660void rf(Register reg, int lsb) {661current->rf(reg, lsb);662}663void srf(Register reg, int lsb) {664current->srf(reg, lsb);665}666void zrf(Register reg, int lsb) {667current->zrf(reg, lsb);668}669void rf(FloatRegister reg, int lsb) {670current->rf(reg, lsb);671}672void fixed(unsigned value, unsigned mask) {673current->fixed(value, mask);674}675676void emit() {677emit_long(current->get_insn());678assert_cond(current->get_bits() == 0xffffffff);679current = NULL;680}681682typedef void (Assembler::* uncond_branch_insn)(address dest);683typedef void (Assembler::* compare_and_branch_insn)(Register Rt, address dest);684typedef void (Assembler::* test_and_branch_insn)(Register Rt, int bitpos, address dest);685typedef void (Assembler::* prefetch_insn)(address target, prfop);686687void wrap_label(Label &L, uncond_branch_insn insn);688void wrap_label(Register r, Label &L, compare_and_branch_insn insn);689void wrap_label(Register r, int bitpos, Label &L, test_and_branch_insn insn);690void wrap_label(Label &L, prfop, prefetch_insn insn);691692// PC-rel. addressing693694void adr(Register Rd, address dest);695void _adrp(Register Rd, address dest);696697void adr(Register Rd, const Address &dest);698void _adrp(Register Rd, const Address &dest);699700void adr(Register Rd, Label &L) {701wrap_label(Rd, L, &Assembler::Assembler::adr);702}703void _adrp(Register Rd, Label &L) {704wrap_label(Rd, L, &Assembler::_adrp);705}706707void adrp(Register Rd, const Address &dest, unsigned long &offset);708709#undef INSN710711void add_sub_immediate(Register Rd, Register Rn, unsigned uimm, int op,712int negated_op);713714// Add/subtract (immediate)715#define INSN(NAME, decode, negated) \716void NAME(Register Rd, Register Rn, unsigned imm, unsigned shift) { \717starti; \718f(decode, 31, 29), f(0b10001, 28, 24), f(shift, 23, 22), f(imm, 21, 10); \719zrf(Rd, 0), srf(Rn, 5); \720} \721\722void NAME(Register Rd, Register Rn, unsigned imm) { \723starti; \724add_sub_immediate(Rd, Rn, imm, decode, negated); \725}726727INSN(addsw, 0b001, 0b011);728INSN(subsw, 0b011, 0b001);729INSN(adds, 0b101, 0b111);730INSN(subs, 0b111, 0b101);731732#undef INSN733734#define INSN(NAME, decode, negated) \735void NAME(Register Rd, Register Rn, unsigned imm) { \736starti; \737add_sub_immediate(Rd, Rn, imm, decode, negated); \738}739740INSN(addw, 0b000, 0b010);741INSN(subw, 0b010, 0b000);742INSN(add, 0b100, 0b110);743INSN(sub, 0b110, 0b100);744745#undef INSN746747// Logical (immediate)748#define INSN(NAME, decode, is32) \749void NAME(Register Rd, Register Rn, uint64_t imm) { \750starti; \751uint32_t val = encode_logical_immediate(is32, imm); \752f(decode, 31, 29), f(0b100100, 28, 23), f(val, 22, 10); \753srf(Rd, 0), zrf(Rn, 5); \754}755756INSN(andw, 0b000, true);757INSN(orrw, 0b001, true);758INSN(eorw, 0b010, true);759INSN(andr, 0b100, false);760INSN(orr, 0b101, false);761INSN(eor, 0b110, false);762763#undef INSN764765#define INSN(NAME, decode, is32) \766void NAME(Register Rd, Register Rn, uint64_t imm) { \767starti; \768uint32_t val = encode_logical_immediate(is32, imm); \769f(decode, 31, 29), f(0b100100, 28, 23), f(val, 22, 10); \770zrf(Rd, 0), zrf(Rn, 5); \771}772773INSN(ands, 0b111, false);774INSN(andsw, 0b011, true);775776#undef INSN777778// Move wide (immediate)779#define INSN(NAME, opcode) \780void NAME(Register Rd, unsigned imm, unsigned shift = 0) { \781assert_cond((shift/16)*16 == shift); \782starti; \783f(opcode, 31, 29), f(0b100101, 28, 23), f(shift/16, 22, 21), \784f(imm, 20, 5); \785rf(Rd, 0); \786}787788INSN(movnw, 0b000);789INSN(movzw, 0b010);790INSN(movkw, 0b011);791INSN(movn, 0b100);792INSN(movz, 0b110);793INSN(movk, 0b111);794795#undef INSN796797// Bitfield798#define INSN(NAME, opcode) \799void NAME(Register Rd, Register Rn, unsigned immr, unsigned imms) { \800starti; \801f(opcode, 31, 22), f(immr, 21, 16), f(imms, 15, 10); \802rf(Rn, 5), rf(Rd, 0); \803}804805INSN(sbfmw, 0b0001001100);806INSN(bfmw, 0b0011001100);807INSN(ubfmw, 0b0101001100);808INSN(sbfm, 0b1001001101);809INSN(bfm, 0b1011001101);810INSN(ubfm, 0b1101001101);811812#undef INSN813814// Extract815#define INSN(NAME, opcode) \816void NAME(Register Rd, Register Rn, Register Rm, unsigned imms) { \817starti; \818f(opcode, 31, 21), f(imms, 15, 10); \819rf(Rm, 16), rf(Rn, 5), rf(Rd, 0); \820}821822INSN(extrw, 0b00010011100);823INSN(extr, 0b10010011110);824825#undef INSN826827// The maximum range of a branch is fixed for the AArch64828// architecture. In debug mode we shrink it in order to test829// trampolines, but not so small that branches in the interpreter830// are out of range.831static const unsigned long branch_range = NOT_DEBUG(128 * M) DEBUG_ONLY(2 * M);832833static bool reachable_from_branch_at(address branch, address target) {834return uabs(target - branch) < branch_range;835}836837// Unconditional branch (immediate)838839#define INSN(NAME, opcode) \840void NAME(address dest) { \841starti; \842long offset = (dest - pc()) >> 2; \843DEBUG_ONLY(assert(reachable_from_branch_at(pc(), dest), "debug only")); \844f(opcode, 31), f(0b00101, 30, 26), sf(offset, 25, 0); \845} \846void NAME(Label &L) { \847wrap_label(L, &Assembler::NAME); \848} \849void NAME(const Address &dest);850851INSN(b, 0);852INSN(bl, 1);853854#undef INSN855856// Compare & branch (immediate)857#define INSN(NAME, opcode) \858void NAME(Register Rt, address dest) { \859long offset = (dest - pc()) >> 2; \860starti; \861f(opcode, 31, 24), sf(offset, 23, 5), rf(Rt, 0); \862} \863void NAME(Register Rt, Label &L) { \864wrap_label(Rt, L, &Assembler::NAME); \865}866867INSN(cbzw, 0b00110100);868INSN(cbnzw, 0b00110101);869INSN(cbz, 0b10110100);870INSN(cbnz, 0b10110101);871872#undef INSN873874// Test & branch (immediate)875#define INSN(NAME, opcode) \876void NAME(Register Rt, int bitpos, address dest) { \877long offset = (dest - pc()) >> 2; \878int b5 = bitpos >> 5; \879bitpos &= 0x1f; \880starti; \881f(b5, 31), f(opcode, 30, 24), f(bitpos, 23, 19), sf(offset, 18, 5); \882rf(Rt, 0); \883} \884void NAME(Register Rt, int bitpos, Label &L) { \885wrap_label(Rt, bitpos, L, &Assembler::NAME); \886}887888INSN(tbz, 0b0110110);889INSN(tbnz, 0b0110111);890891#undef INSN892893// Conditional branch (immediate)894enum Condition895{EQ, NE, HS, CS=HS, LO, CC=LO, MI, PL, VS, VC, HI, LS, GE, LT, GT, LE, AL, NV};896897void br(Condition cond, address dest) {898long offset = (dest - pc()) >> 2;899starti;900f(0b0101010, 31, 25), f(0, 24), sf(offset, 23, 5), f(0, 4), f(cond, 3, 0);901}902903#define INSN(NAME, cond) \904void NAME(address dest) { \905br(cond, dest); \906}907908INSN(beq, EQ);909INSN(bne, NE);910INSN(bhs, HS);911INSN(bcs, CS);912INSN(blo, LO);913INSN(bcc, CC);914INSN(bmi, MI);915INSN(bpl, PL);916INSN(bvs, VS);917INSN(bvc, VC);918INSN(bhi, HI);919INSN(bls, LS);920INSN(bge, GE);921INSN(blt, LT);922INSN(bgt, GT);923INSN(ble, LE);924INSN(bal, AL);925INSN(bnv, NV);926927void br(Condition cc, Label &L);928929#undef INSN930931// Exception generation932void generate_exception(int opc, int op2, int LL, unsigned imm) {933starti;934f(0b11010100, 31, 24);935f(opc, 23, 21), f(imm, 20, 5), f(op2, 4, 2), f(LL, 1, 0);936}937938#define INSN(NAME, opc, op2, LL) \939void NAME(unsigned imm) { \940generate_exception(opc, op2, LL, imm); \941}942943INSN(svc, 0b000, 0, 0b01);944INSN(hvc, 0b000, 0, 0b10);945INSN(smc, 0b000, 0, 0b11);946INSN(brk, 0b001, 0, 0b00);947INSN(hlt, 0b010, 0, 0b00);948INSN(dpcs1, 0b101, 0, 0b01);949INSN(dpcs2, 0b101, 0, 0b10);950INSN(dpcs3, 0b101, 0, 0b11);951952#undef INSN953954// System955void system(int op0, int op1, int CRn, int CRm, int op2,956Register rt = dummy_reg)957{958starti;959f(0b11010101000, 31, 21);960f(op0, 20, 19);961f(op1, 18, 16);962f(CRn, 15, 12);963f(CRm, 11, 8);964f(op2, 7, 5);965rf(rt, 0);966}967968void hint(int imm) {969system(0b00, 0b011, 0b0010, imm, 0b000);970}971972void nop() {973hint(0);974}975// we only provide mrs and msr for the special purpose system976// registers where op1 (instr[20:19]) == 11 and, (currently) only977// use it for FPSR n.b msr has L (instr[21]) == 0 mrs has L == 1978979void msr(int op1, int CRn, int CRm, int op2, Register rt) {980starti;981f(0b1101010100011, 31, 19);982f(op1, 18, 16);983f(CRn, 15, 12);984f(CRm, 11, 8);985f(op2, 7, 5);986// writing zr is ok987zrf(rt, 0);988}989990void mrs(int op1, int CRn, int CRm, int op2, Register rt) {991starti;992f(0b1101010100111, 31, 19);993f(op1, 18, 16);994f(CRn, 15, 12);995f(CRm, 11, 8);996f(op2, 7, 5);997// reading to zr is a mistake998rf(rt, 0);999}10001001enum barrier {OSHLD = 0b0001, OSHST, OSH, NSHLD=0b0101, NSHST, NSH,1002ISHLD = 0b1001, ISHST, ISH, LD=0b1101, ST, SY};10031004void dsb(barrier imm) {1005system(0b00, 0b011, 0b00011, imm, 0b100);1006}10071008void dmb(barrier imm) {1009system(0b00, 0b011, 0b00011, imm, 0b101);1010}10111012void isb() {1013system(0b00, 0b011, 0b00011, SY, 0b110);1014}10151016void sys(int op1, int CRn, int CRm, int op2,1017Register rt = (Register)0b11111) {1018system(0b01, op1, CRn, CRm, op2, rt);1019}10201021// Only implement operations accessible from EL0 or higher, i.e.,1022// op1 CRn CRm op21023// IC IVAU 3 7 5 11024// DC CVAC 3 7 10 11025// DC CVAU 3 7 11 11026// DC CIVAC 3 7 14 11027// DC ZVA 3 7 4 11028// So only deal with the CRm field.1029enum icache_maintenance {IVAU = 0b0101};1030enum dcache_maintenance {CVAC = 0b1010, CVAU = 0b1011, CIVAC = 0b1110, ZVA = 0b100};10311032void dc(dcache_maintenance cm, Register Rt) {1033sys(0b011, 0b0111, cm, 0b001, Rt);1034}10351036void ic(icache_maintenance cm, Register Rt) {1037sys(0b011, 0b0111, cm, 0b001, Rt);1038}10391040// A more convenient access to dmb for our purposes1041enum Membar_mask_bits {1042// We can use ISH for a barrier because the ARM ARM says "This1043// architecture assumes that all Processing Elements that use the1044// same operating system or hypervisor are in the same Inner1045// Shareable shareability domain."1046StoreStore = ISHST,1047LoadStore = ISHLD,1048LoadLoad = ISHLD,1049StoreLoad = ISH,1050AnyAny = ISH1051};10521053void membar(Membar_mask_bits order_constraint) {1054dmb(Assembler::barrier(order_constraint));1055}10561057// Unconditional branch (register)1058void branch_reg(Register R, int opc) {1059starti;1060f(0b1101011, 31, 25);1061f(opc, 24, 21);1062f(0b11111000000, 20, 10);1063rf(R, 5);1064f(0b00000, 4, 0);1065}10661067#define INSN(NAME, opc) \1068void NAME(Register R) { \1069branch_reg(R, opc); \1070}10711072INSN(br, 0b0000);1073INSN(blr, 0b0001);1074INSN(ret, 0b0010);10751076void ret(void *p); // This forces a compile-time error for ret(0)10771078#undef INSN10791080#define INSN(NAME, opc) \1081void NAME() { \1082branch_reg(dummy_reg, opc); \1083}10841085INSN(eret, 0b0100);1086INSN(drps, 0b0101);10871088#undef INSN10891090// Load/store exclusive1091enum operand_size { byte, halfword, word, xword };10921093void load_store_exclusive(Register Rs, Register Rt1, Register Rt2,1094Register Rn, enum operand_size sz, int op, bool ordered) {1095starti;1096f(sz, 31, 30), f(0b001000, 29, 24), f(op, 23, 21);1097rf(Rs, 16), f(ordered, 15), rf(Rt2, 10), srf(Rn, 5), zrf(Rt1, 0);1098}10991100void load_exclusive(Register dst, Register addr,1101enum operand_size sz, bool ordered) {1102load_store_exclusive(dummy_reg, dst, dummy_reg, addr,1103sz, 0b010, ordered);1104}11051106void store_exclusive(Register status, Register new_val, Register addr,1107enum operand_size sz, bool ordered) {1108load_store_exclusive(status, new_val, dummy_reg, addr,1109sz, 0b000, ordered);1110}11111112#define INSN4(NAME, sz, op, o0) /* Four registers */ \1113void NAME(Register Rs, Register Rt1, Register Rt2, Register Rn) { \1114guarantee(Rs != Rn && Rs != Rt1 && Rs != Rt2, "unpredictable instruction"); \1115load_store_exclusive(Rs, Rt1, Rt2, Rn, sz, op, o0); \1116}11171118#define INSN3(NAME, sz, op, o0) /* Three registers */ \1119void NAME(Register Rs, Register Rt, Register Rn) { \1120guarantee(Rs != Rn && Rs != Rt, "unpredictable instruction"); \1121load_store_exclusive(Rs, Rt, dummy_reg, Rn, sz, op, o0); \1122}11231124#define INSN2(NAME, sz, op, o0) /* Two registers */ \1125void NAME(Register Rt, Register Rn) { \1126load_store_exclusive(dummy_reg, Rt, dummy_reg, \1127Rn, sz, op, o0); \1128}11291130#define INSN_FOO(NAME, sz, op, o0) /* Three registers, encoded differently */ \1131void NAME(Register Rt1, Register Rt2, Register Rn) { \1132guarantee(Rt1 != Rt2, "unpredictable instruction"); \1133load_store_exclusive(dummy_reg, Rt1, Rt2, Rn, sz, op, o0); \1134}11351136// bytes1137INSN3(stxrb, byte, 0b000, 0);1138INSN3(stlxrb, byte, 0b000, 1);1139INSN2(ldxrb, byte, 0b010, 0);1140INSN2(ldaxrb, byte, 0b010, 1);1141INSN2(stlrb, byte, 0b100, 1);1142INSN2(ldarb, byte, 0b110, 1);11431144// halfwords1145INSN3(stxrh, halfword, 0b000, 0);1146INSN3(stlxrh, halfword, 0b000, 1);1147INSN2(ldxrh, halfword, 0b010, 0);1148INSN2(ldaxrh, halfword, 0b010, 1);1149INSN2(stlrh, halfword, 0b100, 1);1150INSN2(ldarh, halfword, 0b110, 1);11511152// words1153INSN3(stxrw, word, 0b000, 0);1154INSN3(stlxrw, word, 0b000, 1);1155INSN4(stxpw, word, 0b001, 0);1156INSN4(stlxpw, word, 0b001, 1);1157INSN2(ldxrw, word, 0b010, 0);1158INSN2(ldaxrw, word, 0b010, 1);1159INSN_FOO(ldxpw, word, 0b011, 0);1160INSN_FOO(ldaxpw, word, 0b011, 1);1161INSN2(stlrw, word, 0b100, 1);1162INSN2(ldarw, word, 0b110, 1);11631164// xwords1165INSN3(stxr, xword, 0b000, 0);1166INSN3(stlxr, xword, 0b000, 1);1167INSN4(stxp, xword, 0b001, 0);1168INSN4(stlxp, xword, 0b001, 1);1169INSN2(ldxr, xword, 0b010, 0);1170INSN2(ldaxr, xword, 0b010, 1);1171INSN_FOO(ldxp, xword, 0b011, 0);1172INSN_FOO(ldaxp, xword, 0b011, 1);1173INSN2(stlr, xword, 0b100, 1);1174INSN2(ldar, xword, 0b110, 1);11751176#undef INSN21177#undef INSN31178#undef INSN41179#undef INSN_FOO11801181// 8.1 Compare and swap extensions1182void lse_cas(Register Rs, Register Rt, Register Rn,1183enum operand_size sz, bool a, bool r, bool not_pair) {1184starti;1185if (! not_pair) { // Pair1186assert(sz == word || sz == xword, "invalid size");1187/* The size bit is in bit 30, not 31 */1188sz = (operand_size)(sz == word ? 0b00:0b01);1189}1190f(sz, 31, 30), f(0b001000, 29, 24), f(1, 23), f(a, 22), f(1, 21);1191rf(Rs, 16), f(r, 15), f(0b11111, 14, 10), rf(Rn, 5), rf(Rt, 0);1192}11931194// CAS1195#define INSN(NAME, a, r) \1196void NAME(operand_size sz, Register Rs, Register Rt, Register Rn) { \1197assert(Rs != Rn && Rs != Rt, "unpredictable instruction"); \1198lse_cas(Rs, Rt, Rn, sz, a, r, true); \1199}1200INSN(cas, false, false)1201INSN(casa, true, false)1202INSN(casl, false, true)1203INSN(casal, true, true)1204#undef INSN12051206// CASP1207#define INSN(NAME, a, r) \1208void NAME(operand_size sz, Register Rs, Register Rs1, \1209Register Rt, Register Rt1, Register Rn) { \1210assert((Rs->encoding() & 1) == 0 && (Rt->encoding() & 1) == 0 && \1211Rs->successor() == Rs1 && Rt->successor() == Rt1 && \1212Rs != Rn && Rs1 != Rn && Rs != Rt, "invalid registers"); \1213lse_cas(Rs, Rt, Rn, sz, a, r, false); \1214}1215INSN(casp, false, false)1216INSN(caspa, true, false)1217INSN(caspl, false, true)1218INSN(caspal, true, true)1219#undef INSN12201221// 8.1 Atomic operations1222void lse_atomic(Register Rs, Register Rt, Register Rn,1223enum operand_size sz, int op1, int op2, bool a, bool r) {1224starti;1225f(sz, 31, 30), f(0b111000, 29, 24), f(a, 23), f(r, 22), f(1, 21);1226rf(Rs, 16), f(op1, 15), f(op2, 14, 12), f(0, 11, 10), rf(Rn, 5), zrf(Rt, 0);1227}12281229#define INSN(NAME, NAME_A, NAME_L, NAME_AL, op1, op2) \1230void NAME(operand_size sz, Register Rs, Register Rt, Register Rn) { \1231lse_atomic(Rs, Rt, Rn, sz, op1, op2, false, false); \1232} \1233void NAME_A(operand_size sz, Register Rs, Register Rt, Register Rn) { \1234lse_atomic(Rs, Rt, Rn, sz, op1, op2, true, false); \1235} \1236void NAME_L(operand_size sz, Register Rs, Register Rt, Register Rn) { \1237lse_atomic(Rs, Rt, Rn, sz, op1, op2, false, true); \1238} \1239void NAME_AL(operand_size sz, Register Rs, Register Rt, Register Rn) {\1240lse_atomic(Rs, Rt, Rn, sz, op1, op2, true, true); \1241}1242INSN(ldadd, ldadda, ldaddl, ldaddal, 0, 0b000);1243INSN(ldbic, ldbica, ldbicl, ldbical, 0, 0b001);1244INSN(ldeor, ldeora, ldeorl, ldeoral, 0, 0b010);1245INSN(ldorr, ldorra, ldorrl, ldorral, 0, 0b011);1246INSN(ldsmax, ldsmaxa, ldsmaxl, ldsmaxal, 0, 0b100);1247INSN(ldsmin, ldsmina, ldsminl, ldsminal, 0, 0b101);1248INSN(ldumax, ldumaxa, ldumaxl, ldumaxal, 0, 0b110);1249INSN(ldumin, ldumina, lduminl, lduminal, 0, 0b111);1250INSN(swp, swpa, swpl, swpal, 1, 0b000);1251#undef INSN12521253// Load register (literal)1254#define INSN(NAME, opc, V) \1255void NAME(Register Rt, address dest) { \1256long offset = (dest - pc()) >> 2; \1257starti; \1258f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24), \1259sf(offset, 23, 5); \1260rf(Rt, 0); \1261} \1262void NAME(Register Rt, address dest, relocInfo::relocType rtype) { \1263InstructionMark im(this); \1264guarantee(rtype == relocInfo::internal_word_type, \1265"only internal_word_type relocs make sense here"); \1266code_section()->relocate(inst_mark(), InternalAddress(dest).rspec()); \1267NAME(Rt, dest); \1268} \1269void NAME(Register Rt, Label &L) { \1270wrap_label(Rt, L, &Assembler::NAME); \1271}12721273INSN(ldrw, 0b00, 0);1274INSN(ldr, 0b01, 0);1275INSN(ldrsw, 0b10, 0);12761277#undef INSN12781279#define INSN(NAME, opc, V) \1280void NAME(FloatRegister Rt, address dest) { \1281long offset = (dest - pc()) >> 2; \1282starti; \1283f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24), \1284sf(offset, 23, 5); \1285rf((Register)Rt, 0); \1286}12871288INSN(ldrs, 0b00, 1);1289INSN(ldrd, 0b01, 1);1290INSN(ldrq, 0x10, 1);12911292#undef INSN12931294#define INSN(NAME, opc, V) \1295void NAME(address dest, prfop op = PLDL1KEEP) { \1296long offset = (dest - pc()) >> 2; \1297starti; \1298f(opc, 31, 30), f(0b011, 29, 27), f(V, 26), f(0b00, 25, 24), \1299sf(offset, 23, 5); \1300f(op, 4, 0); \1301} \1302void NAME(Label &L, prfop op = PLDL1KEEP) { \1303wrap_label(L, op, &Assembler::NAME); \1304}13051306INSN(prfm, 0b11, 0);13071308#undef INSN13091310// Load/store1311void ld_st1(int opc, int p1, int V, int L,1312Register Rt1, Register Rt2, Address adr, bool no_allocate) {1313starti;1314f(opc, 31, 30), f(p1, 29, 27), f(V, 26), f(L, 22);1315zrf(Rt2, 10), zrf(Rt1, 0);1316if (no_allocate) {1317adr.encode_nontemporal_pair(current);1318} else {1319adr.encode_pair(current);1320}1321}13221323// Load/store register pair (offset)1324#define INSN(NAME, size, p1, V, L, no_allocate) \1325void NAME(Register Rt1, Register Rt2, Address adr) { \1326ld_st1(size, p1, V, L, Rt1, Rt2, adr, no_allocate); \1327}13281329INSN(stpw, 0b00, 0b101, 0, 0, false);1330INSN(ldpw, 0b00, 0b101, 0, 1, false);1331INSN(ldpsw, 0b01, 0b101, 0, 1, false);1332INSN(stp, 0b10, 0b101, 0, 0, false);1333INSN(ldp, 0b10, 0b101, 0, 1, false);13341335// Load/store no-allocate pair (offset)1336INSN(stnpw, 0b00, 0b101, 0, 0, true);1337INSN(ldnpw, 0b00, 0b101, 0, 1, true);1338INSN(stnp, 0b10, 0b101, 0, 0, true);1339INSN(ldnp, 0b10, 0b101, 0, 1, true);13401341#undef INSN13421343#define INSN(NAME, size, p1, V, L, no_allocate) \1344void NAME(FloatRegister Rt1, FloatRegister Rt2, Address adr) { \1345ld_st1(size, p1, V, L, (Register)Rt1, (Register)Rt2, adr, no_allocate); \1346}13471348INSN(stps, 0b00, 0b101, 1, 0, false);1349INSN(ldps, 0b00, 0b101, 1, 1, false);1350INSN(stpd, 0b01, 0b101, 1, 0, false);1351INSN(ldpd, 0b01, 0b101, 1, 1, false);1352INSN(stpq, 0b10, 0b101, 1, 0, false);1353INSN(ldpq, 0b10, 0b101, 1, 1, false);13541355#undef INSN13561357// Load/store register (all modes)1358void ld_st2(Register Rt, const Address &adr, int size, int op, int V = 0) {1359starti;13601361f(V, 26); // general reg?1362zrf(Rt, 0);13631364// Encoding for literal loads is done here (rather than pushed1365// down into Address::encode) because the encoding of this1366// instruction is too different from all of the other forms to1367// make it worth sharing.1368if (adr.getMode() == Address::literal) {1369assert(size == 0b10 || size == 0b11, "bad operand size in ldr");1370assert(op == 0b01, "literal form can only be used with loads");1371f(size & 0b01, 31, 30), f(0b011, 29, 27), f(0b00, 25, 24);1372long offset = (adr.target() - pc()) >> 2;1373sf(offset, 23, 5);1374code_section()->relocate(pc(), adr.rspec());1375return;1376}13771378f(size, 31, 30);1379f(op, 23, 22); // str1380adr.encode(current);1381}13821383#define INSN(NAME, size, op) \1384void NAME(Register Rt, const Address &adr) { \1385ld_st2(Rt, adr, size, op); \1386} \13871388INSN(str, 0b11, 0b00);1389INSN(strw, 0b10, 0b00);1390INSN(strb, 0b00, 0b00);1391INSN(strh, 0b01, 0b00);13921393INSN(ldr, 0b11, 0b01);1394INSN(ldrw, 0b10, 0b01);1395INSN(ldrb, 0b00, 0b01);1396INSN(ldrh, 0b01, 0b01);13971398INSN(ldrsb, 0b00, 0b10);1399INSN(ldrsbw, 0b00, 0b11);1400INSN(ldrsh, 0b01, 0b10);1401INSN(ldrshw, 0b01, 0b11);1402INSN(ldrsw, 0b10, 0b10);14031404#undef INSN14051406#define INSN(NAME, size, op) \1407void NAME(const Address &adr, prfop pfop = PLDL1KEEP) { \1408ld_st2((Register)pfop, adr, size, op); \1409}14101411INSN(prfm, 0b11, 0b10); // FIXME: PRFM should not be used with1412// writeback modes, but the assembler1413// doesn't enfore that.14141415#undef INSN14161417#define INSN(NAME, size, op) \1418void NAME(FloatRegister Rt, const Address &adr) { \1419ld_st2((Register)Rt, adr, size, op, 1); \1420}14211422INSN(strd, 0b11, 0b00);1423INSN(strs, 0b10, 0b00);1424INSN(ldrd, 0b11, 0b01);1425INSN(ldrs, 0b10, 0b01);1426INSN(strq, 0b00, 0b10);1427INSN(ldrq, 0x00, 0b11);14281429#undef INSN14301431enum shift_kind { LSL, LSR, ASR, ROR };14321433void op_shifted_reg(unsigned decode,1434enum shift_kind kind, unsigned shift,1435unsigned size, unsigned op) {1436f(size, 31);1437f(op, 30, 29);1438f(decode, 28, 24);1439f(shift, 15, 10);1440f(kind, 23, 22);1441}14421443// Logical (shifted register)1444#define INSN(NAME, size, op, N) \1445void NAME(Register Rd, Register Rn, Register Rm, \1446enum shift_kind kind = LSL, unsigned shift = 0) { \1447starti; \1448f(N, 21); \1449zrf(Rm, 16), zrf(Rn, 5), zrf(Rd, 0); \1450op_shifted_reg(0b01010, kind, shift, size, op); \1451}14521453INSN(andr, 1, 0b00, 0);1454INSN(orr, 1, 0b01, 0);1455INSN(eor, 1, 0b10, 0);1456INSN(ands, 1, 0b11, 0);1457INSN(andw, 0, 0b00, 0);1458INSN(orrw, 0, 0b01, 0);1459INSN(eorw, 0, 0b10, 0);1460INSN(andsw, 0, 0b11, 0);14611462INSN(bic, 1, 0b00, 1);1463INSN(orn, 1, 0b01, 1);1464INSN(eon, 1, 0b10, 1);1465INSN(bics, 1, 0b11, 1);1466INSN(bicw, 0, 0b00, 1);1467INSN(ornw, 0, 0b01, 1);1468INSN(eonw, 0, 0b10, 1);1469INSN(bicsw, 0, 0b11, 1);14701471#undef INSN14721473// Add/subtract (shifted register)1474#define INSN(NAME, size, op) \1475void NAME(Register Rd, Register Rn, Register Rm, \1476enum shift_kind kind, unsigned shift = 0) { \1477starti; \1478f(0, 21); \1479assert_cond(kind != ROR); \1480zrf(Rd, 0), zrf(Rn, 5), zrf(Rm, 16); \1481op_shifted_reg(0b01011, kind, shift, size, op); \1482}14831484INSN(add, 1, 0b000);1485INSN(sub, 1, 0b10);1486INSN(addw, 0, 0b000);1487INSN(subw, 0, 0b10);14881489INSN(adds, 1, 0b001);1490INSN(subs, 1, 0b11);1491INSN(addsw, 0, 0b001);1492INSN(subsw, 0, 0b11);14931494#undef INSN14951496// Add/subtract (extended register)1497#define INSN(NAME, op) \1498void NAME(Register Rd, Register Rn, Register Rm, \1499ext::operation option, int amount = 0) { \1500starti; \1501zrf(Rm, 16), srf(Rn, 5), srf(Rd, 0); \1502add_sub_extended_reg(op, 0b01011, Rd, Rn, Rm, 0b00, option, amount); \1503}15041505void add_sub_extended_reg(unsigned op, unsigned decode,1506Register Rd, Register Rn, Register Rm,1507unsigned opt, ext::operation option, unsigned imm) {1508guarantee(imm <= 4, "shift amount must be < 4");1509f(op, 31, 29), f(decode, 28, 24), f(opt, 23, 22), f(1, 21);1510f(option, 15, 13), f(imm, 12, 10);1511}15121513INSN(addw, 0b000);1514INSN(subw, 0b010);1515INSN(add, 0b100);1516INSN(sub, 0b110);15171518#undef INSN15191520#define INSN(NAME, op) \1521void NAME(Register Rd, Register Rn, Register Rm, \1522ext::operation option, int amount = 0) { \1523starti; \1524zrf(Rm, 16), srf(Rn, 5), zrf(Rd, 0); \1525add_sub_extended_reg(op, 0b01011, Rd, Rn, Rm, 0b00, option, amount); \1526}15271528INSN(addsw, 0b001);1529INSN(subsw, 0b011);1530INSN(adds, 0b101);1531INSN(subs, 0b111);15321533#undef INSN15341535// Aliases for short forms of add and sub1536#define INSN(NAME) \1537void NAME(Register Rd, Register Rn, Register Rm) { \1538if (Rd == sp || Rn == sp) \1539NAME(Rd, Rn, Rm, ext::uxtx); \1540else \1541NAME(Rd, Rn, Rm, LSL); \1542}15431544INSN(addw);1545INSN(subw);1546INSN(add);1547INSN(sub);15481549INSN(addsw);1550INSN(subsw);1551INSN(adds);1552INSN(subs);15531554#undef INSN15551556// Add/subtract (with carry)1557void add_sub_carry(unsigned op, Register Rd, Register Rn, Register Rm) {1558starti;1559f(op, 31, 29);1560f(0b11010000, 28, 21);1561f(0b000000, 15, 10);1562zrf(Rm, 16), zrf(Rn, 5), zrf(Rd, 0);1563}15641565#define INSN(NAME, op) \1566void NAME(Register Rd, Register Rn, Register Rm) { \1567add_sub_carry(op, Rd, Rn, Rm); \1568}15691570INSN(adcw, 0b000);1571INSN(adcsw, 0b001);1572INSN(sbcw, 0b010);1573INSN(sbcsw, 0b011);1574INSN(adc, 0b100);1575INSN(adcs, 0b101);1576INSN(sbc,0b110);1577INSN(sbcs, 0b111);15781579#undef INSN15801581// Conditional compare (both kinds)1582void conditional_compare(unsigned op, int o2, int o3,1583Register Rn, unsigned imm5, unsigned nzcv,1584unsigned cond) {1585f(op, 31, 29);1586f(0b11010010, 28, 21);1587f(cond, 15, 12);1588f(o2, 10);1589f(o3, 4);1590f(nzcv, 3, 0);1591f(imm5, 20, 16), rf(Rn, 5);1592}15931594#define INSN(NAME, op) \1595void NAME(Register Rn, Register Rm, int imm, Condition cond) { \1596starti; \1597f(0, 11); \1598conditional_compare(op, 0, 0, Rn, (uintptr_t)Rm, imm, cond); \1599} \1600\1601void NAME(Register Rn, int imm5, int imm, Condition cond) { \1602starti; \1603f(1, 11); \1604conditional_compare(op, 0, 0, Rn, imm5, imm, cond); \1605}16061607INSN(ccmnw, 0b001);1608INSN(ccmpw, 0b011);1609INSN(ccmn, 0b101);1610INSN(ccmp, 0b111);16111612#undef INSN16131614// Conditional select1615void conditional_select(unsigned op, unsigned op2,1616Register Rd, Register Rn, Register Rm,1617unsigned cond) {1618starti;1619f(op, 31, 29);1620f(0b11010100, 28, 21);1621f(cond, 15, 12);1622f(op2, 11, 10);1623zrf(Rm, 16), zrf(Rn, 5), rf(Rd, 0);1624}16251626#define INSN(NAME, op, op2) \1627void NAME(Register Rd, Register Rn, Register Rm, Condition cond) { \1628conditional_select(op, op2, Rd, Rn, Rm, cond); \1629}16301631INSN(cselw, 0b000, 0b00);1632INSN(csincw, 0b000, 0b01);1633INSN(csinvw, 0b010, 0b00);1634INSN(csnegw, 0b010, 0b01);1635INSN(csel, 0b100, 0b00);1636INSN(csinc, 0b100, 0b01);1637INSN(csinv, 0b110, 0b00);1638INSN(csneg, 0b110, 0b01);16391640#undef INSN16411642// Data processing1643void data_processing(unsigned op29, unsigned opcode,1644Register Rd, Register Rn) {1645f(op29, 31, 29), f(0b11010110, 28, 21);1646f(opcode, 15, 10);1647rf(Rn, 5), rf(Rd, 0);1648}16491650// (1 source)1651#define INSN(NAME, op29, opcode2, opcode) \1652void NAME(Register Rd, Register Rn) { \1653starti; \1654f(opcode2, 20, 16); \1655data_processing(op29, opcode, Rd, Rn); \1656}16571658INSN(rbitw, 0b010, 0b00000, 0b00000);1659INSN(rev16w, 0b010, 0b00000, 0b00001);1660INSN(revw, 0b010, 0b00000, 0b00010);1661INSN(clzw, 0b010, 0b00000, 0b00100);1662INSN(clsw, 0b010, 0b00000, 0b00101);16631664INSN(rbit, 0b110, 0b00000, 0b00000);1665INSN(rev16, 0b110, 0b00000, 0b00001);1666INSN(rev32, 0b110, 0b00000, 0b00010);1667INSN(rev, 0b110, 0b00000, 0b00011);1668INSN(clz, 0b110, 0b00000, 0b00100);1669INSN(cls, 0b110, 0b00000, 0b00101);16701671#undef INSN16721673// (2 sources)1674#define INSN(NAME, op29, opcode) \1675void NAME(Register Rd, Register Rn, Register Rm) { \1676starti; \1677rf(Rm, 16); \1678data_processing(op29, opcode, Rd, Rn); \1679}16801681INSN(udivw, 0b000, 0b000010);1682INSN(sdivw, 0b000, 0b000011);1683INSN(lslvw, 0b000, 0b001000);1684INSN(lsrvw, 0b000, 0b001001);1685INSN(asrvw, 0b000, 0b001010);1686INSN(rorvw, 0b000, 0b001011);16871688INSN(udiv, 0b100, 0b000010);1689INSN(sdiv, 0b100, 0b000011);1690INSN(lslv, 0b100, 0b001000);1691INSN(lsrv, 0b100, 0b001001);1692INSN(asrv, 0b100, 0b001010);1693INSN(rorv, 0b100, 0b001011);16941695#undef INSN16961697// (3 sources)1698void data_processing(unsigned op54, unsigned op31, unsigned o0,1699Register Rd, Register Rn, Register Rm,1700Register Ra) {1701starti;1702f(op54, 31, 29), f(0b11011, 28, 24);1703f(op31, 23, 21), f(o0, 15);1704zrf(Rm, 16), zrf(Ra, 10), zrf(Rn, 5), zrf(Rd, 0);1705}17061707#define INSN(NAME, op54, op31, o0) \1708void NAME(Register Rd, Register Rn, Register Rm, Register Ra) { \1709data_processing(op54, op31, o0, Rd, Rn, Rm, Ra); \1710}17111712INSN(maddw, 0b000, 0b000, 0);1713INSN(msubw, 0b000, 0b000, 1);1714INSN(madd, 0b100, 0b000, 0);1715INSN(msub, 0b100, 0b000, 1);1716INSN(smaddl, 0b100, 0b001, 0);1717INSN(smsubl, 0b100, 0b001, 1);1718INSN(umaddl, 0b100, 0b101, 0);1719INSN(umsubl, 0b100, 0b101, 1);17201721#undef INSN17221723#define INSN(NAME, op54, op31, o0) \1724void NAME(Register Rd, Register Rn, Register Rm) { \1725data_processing(op54, op31, o0, Rd, Rn, Rm, (Register)31); \1726}17271728INSN(smulh, 0b100, 0b010, 0);1729INSN(umulh, 0b100, 0b110, 0);17301731#undef INSN17321733// Floating-point data-processing (1 source)1734void data_processing(unsigned op31, unsigned type, unsigned opcode,1735FloatRegister Vd, FloatRegister Vn) {1736starti;1737f(op31, 31, 29);1738f(0b11110, 28, 24);1739f(type, 23, 22), f(1, 21), f(opcode, 20, 15), f(0b10000, 14, 10);1740rf(Vn, 5), rf(Vd, 0);1741}17421743#define INSN(NAME, op31, type, opcode) \1744void NAME(FloatRegister Vd, FloatRegister Vn) { \1745data_processing(op31, type, opcode, Vd, Vn); \1746}17471748private:1749INSN(i_fmovs, 0b000, 0b00, 0b000000);1750public:1751INSN(fabss, 0b000, 0b00, 0b000001);1752INSN(fnegs, 0b000, 0b00, 0b000010);1753INSN(fsqrts, 0b000, 0b00, 0b000011);1754INSN(fcvts, 0b000, 0b00, 0b000101); // Single-precision to double-precision17551756private:1757INSN(i_fmovd, 0b000, 0b01, 0b000000);1758public:1759INSN(fabsd, 0b000, 0b01, 0b000001);1760INSN(fnegd, 0b000, 0b01, 0b000010);1761INSN(fsqrtd, 0b000, 0b01, 0b000011);1762INSN(fcvtd, 0b000, 0b01, 0b000100); // Double-precision to single-precision17631764void fmovd(FloatRegister Vd, FloatRegister Vn) {1765assert(Vd != Vn, "should be");1766i_fmovd(Vd, Vn);1767}17681769void fmovs(FloatRegister Vd, FloatRegister Vn) {1770assert(Vd != Vn, "should be");1771i_fmovs(Vd, Vn);1772}17731774#undef INSN17751776// Floating-point data-processing (2 source)1777void data_processing(unsigned op31, unsigned type, unsigned opcode,1778FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) {1779starti;1780f(op31, 31, 29);1781f(0b11110, 28, 24);1782f(type, 23, 22), f(1, 21), f(opcode, 15, 12), f(0b10, 11, 10);1783rf(Vm, 16), rf(Vn, 5), rf(Vd, 0);1784}17851786#define INSN(NAME, op31, type, opcode) \1787void NAME(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) { \1788data_processing(op31, type, opcode, Vd, Vn, Vm); \1789}17901791INSN(fmuls, 0b000, 0b00, 0b0000);1792INSN(fdivs, 0b000, 0b00, 0b0001);1793INSN(fadds, 0b000, 0b00, 0b0010);1794INSN(fsubs, 0b000, 0b00, 0b0011);1795INSN(fnmuls, 0b000, 0b00, 0b1000);17961797INSN(fmuld, 0b000, 0b01, 0b0000);1798INSN(fdivd, 0b000, 0b01, 0b0001);1799INSN(faddd, 0b000, 0b01, 0b0010);1800INSN(fsubd, 0b000, 0b01, 0b0011);1801INSN(fnmuld, 0b000, 0b01, 0b1000);18021803#undef INSN18041805// Floating-point data-processing (3 source)1806void data_processing(unsigned op31, unsigned type, unsigned o1, unsigned o0,1807FloatRegister Vd, FloatRegister Vn, FloatRegister Vm,1808FloatRegister Va) {1809starti;1810f(op31, 31, 29);1811f(0b11111, 28, 24);1812f(type, 23, 22), f(o1, 21), f(o0, 15);1813rf(Vm, 16), rf(Va, 10), rf(Vn, 5), rf(Vd, 0);1814}18151816#define INSN(NAME, op31, type, o1, o0) \1817void NAME(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm, \1818FloatRegister Va) { \1819data_processing(op31, type, o1, o0, Vd, Vn, Vm, Va); \1820}18211822INSN(fmadds, 0b000, 0b00, 0, 0);1823INSN(fmsubs, 0b000, 0b00, 0, 1);1824INSN(fnmadds, 0b000, 0b00, 1, 0);1825INSN(fnmsubs, 0b000, 0b00, 1, 1);18261827INSN(fmaddd, 0b000, 0b01, 0, 0);1828INSN(fmsubd, 0b000, 0b01, 0, 1);1829INSN(fnmaddd, 0b000, 0b01, 1, 0);1830INSN(fnmsub, 0b000, 0b01, 1, 1);18311832#undef INSN18331834// Floating-point conditional select1835void fp_conditional_select(unsigned op31, unsigned type,1836unsigned op1, unsigned op2,1837Condition cond, FloatRegister Vd,1838FloatRegister Vn, FloatRegister Vm) {1839starti;1840f(op31, 31, 29);1841f(0b11110, 28, 24);1842f(type, 23, 22);1843f(op1, 21, 21);1844f(op2, 11, 10);1845f(cond, 15, 12);1846rf(Vm, 16), rf(Vn, 5), rf(Vd, 0);1847}18481849#define INSN(NAME, op31, type, op1, op2) \1850void NAME(FloatRegister Vd, FloatRegister Vn, \1851FloatRegister Vm, Condition cond) { \1852fp_conditional_select(op31, type, op1, op2, cond, Vd, Vn, Vm); \1853}18541855INSN(fcsels, 0b000, 0b00, 0b1, 0b11);1856INSN(fcseld, 0b000, 0b01, 0b1, 0b11);18571858#undef INSN18591860// Floating-point<->integer conversions1861void float_int_convert(unsigned op31, unsigned type,1862unsigned rmode, unsigned opcode,1863Register Rd, Register Rn) {1864starti;1865f(op31, 31, 29);1866f(0b11110, 28, 24);1867f(type, 23, 22), f(1, 21), f(rmode, 20, 19);1868f(opcode, 18, 16), f(0b000000, 15, 10);1869zrf(Rn, 5), zrf(Rd, 0);1870}18711872#define INSN(NAME, op31, type, rmode, opcode) \1873void NAME(Register Rd, FloatRegister Vn) { \1874float_int_convert(op31, type, rmode, opcode, Rd, (Register)Vn); \1875}18761877INSN(fcvtzsw, 0b000, 0b00, 0b11, 0b000);1878INSN(fcvtzs, 0b100, 0b00, 0b11, 0b000);1879INSN(fcvtzdw, 0b000, 0b01, 0b11, 0b000);1880INSN(fcvtzd, 0b100, 0b01, 0b11, 0b000);18811882INSN(fmovs, 0b000, 0b00, 0b00, 0b110);1883INSN(fmovd, 0b100, 0b01, 0b00, 0b110);18841885// INSN(fmovhid, 0b100, 0b10, 0b01, 0b110);18861887#undef INSN18881889#define INSN(NAME, op31, type, rmode, opcode) \1890void NAME(FloatRegister Vd, Register Rn) { \1891float_int_convert(op31, type, rmode, opcode, (Register)Vd, Rn); \1892}18931894INSN(fmovs, 0b000, 0b00, 0b00, 0b111);1895INSN(fmovd, 0b100, 0b01, 0b00, 0b111);18961897INSN(scvtfws, 0b000, 0b00, 0b00, 0b010);1898INSN(scvtfs, 0b100, 0b00, 0b00, 0b010);1899INSN(scvtfwd, 0b000, 0b01, 0b00, 0b010);1900INSN(scvtfd, 0b100, 0b01, 0b00, 0b010);19011902// INSN(fmovhid, 0b100, 0b10, 0b01, 0b111);19031904#undef INSN19051906// Floating-point compare1907void float_compare(unsigned op31, unsigned type,1908unsigned op, unsigned op2,1909FloatRegister Vn, FloatRegister Vm = (FloatRegister)0) {1910starti;1911f(op31, 31, 29);1912f(0b11110, 28, 24);1913f(type, 23, 22), f(1, 21);1914f(op, 15, 14), f(0b1000, 13, 10), f(op2, 4, 0);1915rf(Vn, 5), rf(Vm, 16);1916}191719181919#define INSN(NAME, op31, type, op, op2) \1920void NAME(FloatRegister Vn, FloatRegister Vm) { \1921float_compare(op31, type, op, op2, Vn, Vm); \1922}19231924#define INSN1(NAME, op31, type, op, op2) \1925void NAME(FloatRegister Vn, double d) { \1926assert_cond(d == 0.0); \1927float_compare(op31, type, op, op2, Vn); \1928}19291930INSN(fcmps, 0b000, 0b00, 0b00, 0b00000);1931INSN1(fcmps, 0b000, 0b00, 0b00, 0b01000);1932// INSN(fcmpes, 0b000, 0b00, 0b00, 0b10000);1933// INSN1(fcmpes, 0b000, 0b00, 0b00, 0b11000);19341935INSN(fcmpd, 0b000, 0b01, 0b00, 0b00000);1936INSN1(fcmpd, 0b000, 0b01, 0b00, 0b01000);1937// INSN(fcmped, 0b000, 0b01, 0b00, 0b10000);1938// INSN1(fcmped, 0b000, 0b01, 0b00, 0b11000);19391940#undef INSN1941#undef INSN119421943// Floating-point Move (immediate)1944private:1945unsigned pack(double value);19461947void fmov_imm(FloatRegister Vn, double value, unsigned size) {1948starti;1949f(0b00011110, 31, 24), f(size, 23, 22), f(1, 21);1950f(pack(value), 20, 13), f(0b10000000, 12, 5);1951rf(Vn, 0);1952}19531954public:19551956void fmovs(FloatRegister Vn, double value) {1957if (value)1958fmov_imm(Vn, value, 0b00);1959else1960fmovs(Vn, zr);1961}1962void fmovd(FloatRegister Vn, double value) {1963if (value)1964fmov_imm(Vn, value, 0b01);1965else1966fmovd(Vn, zr);1967}19681969/* SIMD extensions1970*1971* We just use FloatRegister in the following. They are exactly the same1972* as SIMD registers.1973*/1974public:19751976enum SIMD_Arrangement {1977T8B, T16B, T4H, T8H, T2S, T4S, T1D, T2D1978};19791980enum SIMD_RegVariant {1981B, H, S, D, Q1982};19831984#define INSN(NAME, op) \1985void NAME(FloatRegister Rt, SIMD_RegVariant T, const Address &adr) { \1986ld_st2((Register)Rt, adr, (int)T & 3, op + ((T==Q) ? 0b10:0b00), 1); \1987} \19881989INSN(ldr, 1);1990INSN(str, 0);19911992#undef INSN19931994private:19951996void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn, int op1, int op2) {1997starti;1998f(0,31), f((int)T & 1, 30);1999f(op1, 29, 21), f(0, 20, 16), f(op2, 15, 12);2000f((int)T >> 1, 11, 10), rf(Xn, 5), rf(Vt, 0);2001}2002void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn,2003int imm, int op1, int op2) {2004starti;2005f(0,31), f((int)T & 1, 30);2006f(op1 | 0b100, 29, 21), f(0b11111, 20, 16), f(op2, 15, 12);2007f((int)T >> 1, 11, 10), rf(Xn, 5), rf(Vt, 0);2008}2009void ld_st(FloatRegister Vt, SIMD_Arrangement T, Register Xn,2010Register Xm, int op1, int op2) {2011starti;2012f(0,31), f((int)T & 1, 30);2013f(op1 | 0b100, 29, 21), rf(Xm, 16), f(op2, 15, 12);2014f((int)T >> 1, 11, 10), rf(Xn, 5), rf(Vt, 0);2015}20162017void ld_st(FloatRegister Vt, SIMD_Arrangement T, Address a, int op1, int op2) {2018switch (a.getMode()) {2019case Address::base_plus_offset:2020guarantee(a.offset() == 0, "no offset allowed here");2021ld_st(Vt, T, a.base(), op1, op2);2022break;2023case Address::post:2024ld_st(Vt, T, a.base(), a.offset(), op1, op2);2025break;2026case Address::base_plus_offset_reg:2027ld_st(Vt, T, a.base(), a.index(), op1, op2);2028break;2029default:2030ShouldNotReachHere();2031}2032}20332034public:20352036#define INSN1(NAME, op1, op2) \2037void NAME(FloatRegister Vt, SIMD_Arrangement T, const Address &a) { \2038ld_st(Vt, T, a, op1, op2); \2039}20402041#define INSN2(NAME, op1, op2) \2042void NAME(FloatRegister Vt, FloatRegister Vt2, SIMD_Arrangement T, const Address &a) { \2043assert(Vt->successor() == Vt2, "Registers must be ordered"); \2044ld_st(Vt, T, a, op1, op2); \2045}20462047#define INSN3(NAME, op1, op2) \2048void NAME(FloatRegister Vt, FloatRegister Vt2, FloatRegister Vt3, \2049SIMD_Arrangement T, const Address &a) { \2050assert(Vt->successor() == Vt2 && Vt2->successor() == Vt3, \2051"Registers must be ordered"); \2052ld_st(Vt, T, a, op1, op2); \2053}20542055#define INSN4(NAME, op1, op2) \2056void NAME(FloatRegister Vt, FloatRegister Vt2, FloatRegister Vt3, \2057FloatRegister Vt4, SIMD_Arrangement T, const Address &a) { \2058assert(Vt->successor() == Vt2 && Vt2->successor() == Vt3 && \2059Vt3->successor() == Vt4, "Registers must be ordered"); \2060ld_st(Vt, T, a, op1, op2); \2061}20622063INSN1(ld1, 0b001100010, 0b0111);2064INSN2(ld1, 0b001100010, 0b1010);2065INSN3(ld1, 0b001100010, 0b0110);2066INSN4(ld1, 0b001100010, 0b0010);20672068INSN2(ld2, 0b001100010, 0b1000);2069INSN3(ld3, 0b001100010, 0b0100);2070INSN4(ld4, 0b001100010, 0b0000);20712072INSN1(st1, 0b001100000, 0b0111);2073INSN2(st1, 0b001100000, 0b1010);2074INSN3(st1, 0b001100000, 0b0110);2075INSN4(st1, 0b001100000, 0b0010);20762077INSN2(st2, 0b001100000, 0b1000);2078INSN3(st3, 0b001100000, 0b0100);2079INSN4(st4, 0b001100000, 0b0000);20802081INSN1(ld1r, 0b001101010, 0b1100);2082INSN2(ld2r, 0b001101011, 0b1100);2083INSN3(ld3r, 0b001101010, 0b1110);2084INSN4(ld4r, 0b001101011, 0b1110);20852086#undef INSN12087#undef INSN22088#undef INSN32089#undef INSN420902091#define INSN(NAME, opc) \2092void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \2093starti; \2094assert(T == T8B || T == T16B, "must be T8B or T16B"); \2095f(0, 31), f((int)T & 1, 30), f(opc, 29, 21); \2096rf(Vm, 16), f(0b000111, 15, 10), rf(Vn, 5), rf(Vd, 0); \2097}20982099INSN(eor, 0b101110001);2100INSN(orr, 0b001110101);2101INSN(andr, 0b001110001);2102INSN(bic, 0b001110011);2103INSN(bif, 0b101110111);2104INSN(bit, 0b101110101);2105INSN(bsl, 0b101110011);2106INSN(orn, 0b001110111);21072108#undef INSN21092110#define INSN(NAME, opc, opc2) \2111void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \2112starti; \2113f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24); \2114f((int)T >> 1, 23, 22), f(1, 21), rf(Vm, 16), f(opc2, 15, 10); \2115rf(Vn, 5), rf(Vd, 0); \2116}21172118INSN(addv, 0, 0b100001);2119INSN(subv, 1, 0b100001);2120INSN(mulv, 0, 0b100111);2121INSN(mlav, 0, 0b100101);2122INSN(mlsv, 1, 0b100101);2123INSN(sshl, 0, 0b010001);2124INSN(ushl, 1, 0b010001);21252126#undef INSN21272128#define INSN(NAME, opc, opc2) \2129void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { \2130starti; \2131f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24); \2132f((int)T >> 1, 23, 22), f(opc2, 21, 10); \2133rf(Vn, 5), rf(Vd, 0); \2134}21352136INSN(absr, 0, 0b100000101110);2137INSN(negr, 1, 0b100000101110);2138INSN(notr, 1, 0b100000010110);2139INSN(addv, 0, 0b110001101110);2140INSN(cls, 0, 0b100000010010);2141INSN(clz, 1, 0b100000010010);2142INSN(cnt, 0, 0b100000010110);21432144#undef INSN21452146#define INSN(NAME, op0, cmode0) \2147void NAME(FloatRegister Vd, SIMD_Arrangement T, unsigned imm8, unsigned lsl = 0) { \2148unsigned cmode = cmode0; \2149unsigned op = op0; \2150starti; \2151assert(lsl == 0 || \2152((T == T4H || T == T8H) && lsl == 8) || \2153((T == T2S || T == T4S) && ((lsl >> 3) < 4)), "invalid shift"); \2154cmode |= lsl >> 2; \2155if (T == T4H || T == T8H) cmode |= 0b1000; \2156if (!(T == T4H || T == T8H || T == T2S || T == T4S)) { \2157assert(op == 0 && cmode0 == 0, "must be MOVI"); \2158cmode = 0b1110; \2159if (T == T1D || T == T2D) op = 1; \2160} \2161f(0, 31), f((int)T & 1, 30), f(op, 29), f(0b0111100000, 28, 19); \2162f(imm8 >> 5, 18, 16), f(cmode, 15, 12), f(0x01, 11, 10), f(imm8 & 0b11111, 9, 5); \2163rf(Vd, 0); \2164}21652166INSN(movi, 0, 0);2167INSN(orri, 0, 1);2168INSN(mvni, 1, 0);2169INSN(bici, 1, 1);21702171#undef INSN21722173#define INSN(NAME, op1, op2, op3) \2174void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \2175starti; \2176assert(T == T2S || T == T4S || T == T2D, "invalid arrangement"); \2177f(0, 31), f((int)T & 1, 30), f(op1, 29), f(0b01110, 28, 24), f(op2, 23); \2178f(T==T2D ? 1:0, 22); f(1, 21), rf(Vm, 16), f(op3, 15, 10), rf(Vn, 5), rf(Vd, 0); \2179}21802181INSN(fadd, 0, 0, 0b110101);2182INSN(fdiv, 1, 0, 0b111111);2183INSN(fmul, 1, 0, 0b110111);2184INSN(fsub, 0, 1, 0b110101);21852186#undef INSN21872188#define INSN(NAME, opc) \2189void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm) { \2190starti; \2191assert(T == T4S, "arrangement must be T4S"); \2192f(0b01011110000, 31, 21), rf(Vm, 16), f(opc, 15, 10), rf(Vn, 5), rf(Vd, 0); \2193}21942195INSN(sha1c, 0b000000);2196INSN(sha1m, 0b001000);2197INSN(sha1p, 0b000100);2198INSN(sha1su0, 0b001100);2199INSN(sha256h2, 0b010100);2200INSN(sha256h, 0b010000);2201INSN(sha256su1, 0b011000);22022203#undef INSN22042205#define INSN(NAME, opc) \2206void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { \2207starti; \2208assert(T == T4S, "arrangement must be T4S"); \2209f(0b0101111000101000, 31, 16), f(opc, 15, 10), rf(Vn, 5), rf(Vd, 0); \2210}22112212INSN(sha1h, 0b000010);2213INSN(sha1su1, 0b000110);2214INSN(sha256su0, 0b001010);22152216#undef INSN22172218#define INSN(NAME, opc) \2219void NAME(FloatRegister Vd, FloatRegister Vn) { \2220starti; \2221f(opc, 31, 10), rf(Vn, 5), rf(Vd, 0); \2222}22232224INSN(aese, 0b0100111000101000010010);2225INSN(aesd, 0b0100111000101000010110);2226INSN(aesmc, 0b0100111000101000011010);2227INSN(aesimc, 0b0100111000101000011110);22282229#undef INSN22302231void ins(FloatRegister Vd, SIMD_RegVariant T, FloatRegister Vn, int didx, int sidx) {2232starti;2233assert(T != Q, "invalid register variant");2234f(0b01101110000, 31, 21), f(((didx<<1)|1)<<(int)T, 20, 16), f(0, 15);2235f(sidx<<(int)T, 14, 11), f(1, 10), rf(Vn, 5), rf(Vd, 0);2236}22372238void umov(Register Rd, FloatRegister Vn, SIMD_RegVariant T, int idx) {2239starti;2240f(0, 31), f(T==D ? 1:0, 30), f(0b001110000, 29, 21);2241f(((idx<<1)|1)<<(int)T, 20, 16), f(0b001111, 15, 10);2242rf(Vn, 5), rf(Rd, 0);2243}22442245#define INSN(NAME, opc, opc2) \2246void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int shift){ \2247starti; \2248/* The encodings for the immh:immb fields (bits 22:16) are \2249* 0001 xxx 8B/16B, shift = xxx \2250* 001x xxx 4H/8H, shift = xxxx \2251* 01xx xxx 2S/4S, shift = xxxxx \2252* 1xxx xxx 1D/2D, shift = xxxxxx (1D is RESERVED) \2253*/ \2254assert((1 << ((T>>1)+3)) > shift, "Invalid Shift value"); \2255f(0, 31), f(T & 1, 30), f(opc, 29), f(0b011110, 28, 23), \2256f((1 << ((T>>1)+3))|shift, 22, 16); f(opc2, 15, 10), rf(Vn, 5), rf(Vd, 0); \2257}22582259INSN(shl, 0, 0b010101);2260INSN(sshr, 0, 0b000001);2261INSN(ushr, 1, 0b000001);22622263#undef INSN22642265void ushll(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) {2266starti;2267/* The encodings for the immh:immb fields (bits 22:16) are2268* 0001 xxx 8H, 8B/16b shift = xxx2269* 001x xxx 4S, 4H/8H shift = xxxx2270* 01xx xxx 2D, 2S/4S shift = xxxxx2271* 1xxx xxx RESERVED2272*/2273assert((Tb >> 1) + 1 == (Ta >> 1), "Incompatible arrangement");2274assert((1 << ((Tb>>1)+3)) > shift, "Invalid shift value");2275f(0, 31), f(Tb & 1, 30), f(0b1011110, 29, 23), f((1 << ((Tb>>1)+3))|shift, 22, 16);2276f(0b101001, 15, 10), rf(Vn, 5), rf(Vd, 0);2277}2278void ushll2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, SIMD_Arrangement Tb, int shift) {2279ushll(Vd, Ta, Vn, Tb, shift);2280}22812282void uzp1(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement T, int op = 0){2283starti;2284f(0, 31), f((T & 0x1), 30), f(0b001110, 29, 24), f((T >> 1), 23, 22), f(0, 21);2285rf(Vm, 16), f(0, 15), f(op, 14), f(0b0110, 13, 10), rf(Vn, 5), rf(Vd, 0);2286}2287void uzp2(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement T){2288uzp1(Vd, Vn, Vm, T, 1);2289}22902291// Move from general purpose register2292// mov Vd.T[index], Rn2293void mov(FloatRegister Vd, SIMD_Arrangement T, int index, Register Xn) {2294starti;2295f(0b01001110000, 31, 21), f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16);2296f(0b000111, 15, 10), rf(Xn, 5), rf(Vd, 0);2297}22982299// Move to general purpose register2300// mov Rd, Vn.T[index]2301void mov(Register Xd, FloatRegister Vn, SIMD_Arrangement T, int index) {2302starti;2303f(0, 31), f((T >= T1D) ? 1:0, 30), f(0b001110000, 29, 21);2304f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16);2305f(0b001111, 15, 10), rf(Vn, 5), rf(Xd, 0);2306}23072308// We do not handle the 1Q arrangement.2309void pmull(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) {2310starti;2311assert(Ta == T8H && (Tb == T8B || Tb == T16B), "Invalid Size specifier");2312f(0, 31), f(Tb & 1, 30), f(0b001110001, 29, 21), rf(Vm, 16), f(0b111000, 15, 10);2313rf(Vn, 5), rf(Vd, 0);2314}2315void pmull2(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) {2316pmull(Vd, Ta, Vn, Vm, Tb);2317}23182319void uqxtn(FloatRegister Vd, SIMD_Arrangement Tb, FloatRegister Vn, SIMD_Arrangement Ta) {2320starti;2321int size_b = (int)Tb >> 1;2322int size_a = (int)Ta >> 1;2323assert(size_b < 3 && size_b == size_a - 1, "Invalid size specifier");2324f(0, 31), f(Tb & 1, 30), f(0b101110, 29, 24), f(size_b, 23, 22);2325f(0b100001010010, 21, 10), rf(Vn, 5), rf(Vd, 0);2326}23272328void rev32(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn)2329{2330starti;2331assert(T <= T8H, "must be one of T8B, T16B, T4H, T8H");2332f(0, 31), f((int)T & 1, 30), f(0b101110, 29, 24);2333f(T <= T16B ? 0b00 : 0b01, 23, 22), f(0b100000000010, 21, 10);2334rf(Vn, 5), rf(Vd, 0);2335}23362337void dup(FloatRegister Vd, SIMD_Arrangement T, Register Xs)2338{2339starti;2340assert(T != T1D, "reserved encoding");2341f(0,31), f((int)T & 1, 30), f(0b001110000, 29, 21);2342f((1 << (T >> 1)), 20, 16), f(0b000011, 15, 10), rf(Xs, 5), rf(Vd, 0);2343}23442345void dup(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int index = 0)2346{2347starti;2348assert(T != T1D, "reserved encoding");2349f(0, 31), f((int)T & 1, 30), f(0b001110000, 29, 21);2350f(((1 << (T >> 1)) | (index << ((T >> 1) + 1))), 20, 16);2351f(0b000001, 15, 10), rf(Vn, 5), rf(Vd, 0);2352}23532354// CRC32 instructions2355#define INSN(NAME, sf, sz) \2356void NAME(Register Rd, Register Rn, Register Rm) { \2357starti; \2358f(sf, 31), f(0b0011010110, 30, 21), f(0b0100, 15, 12), f(sz, 11, 10); \2359rf(Rm, 16), rf(Rn, 5), rf(Rd, 0); \2360}23612362INSN(crc32b, 0, 0b00);2363INSN(crc32h, 0, 0b01);2364INSN(crc32w, 0, 0b10);2365INSN(crc32x, 1, 0b11);23662367#undef INSN23682369Assembler(CodeBuffer* code) : AbstractAssembler(code) {2370}23712372virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr,2373Register tmp,2374int offset) {2375ShouldNotCallThis();2376return RegisterOrConstant();2377}23782379// Stack overflow checking2380virtual void bang_stack_with_offset(int offset);23812382static bool operand_valid_for_logical_immediate(bool is32, uint64_t imm);2383static bool operand_valid_for_add_sub_immediate(long imm);2384static bool operand_valid_for_float_immediate(double imm);23852386void emit_data64(jlong data, relocInfo::relocType rtype, int format = 0);2387void emit_data64(jlong data, RelocationHolder const& rspec, int format = 0);2388};23892390inline Assembler::Membar_mask_bits operator|(Assembler::Membar_mask_bits a,2391Assembler::Membar_mask_bits b) {2392return Assembler::Membar_mask_bits(unsigned(a)|unsigned(b));2393}23942395Instruction_aarch64::~Instruction_aarch64() {2396assem->emit();2397}23982399#undef starti24002401// Invert a condition2402inline const Assembler::Condition operator~(const Assembler::Condition cond) {2403return Assembler::Condition(int(cond) ^ 1);2404}24052406class BiasedLockingCounters;24072408extern "C" void das(uint64_t start, int len);24092410#endif // CPU_AARCH64_VM_ASSEMBLER_AARCH64_HPP241124122413