Path: blob/master/dep/vixl/src/aarch32/operands-aarch32.cc
4261 views
// Copyright 2017, VIXL authors1// All rights reserved.2//3// Redistribution and use in source and binary forms, with or without4// modification, are permitted provided that the following conditions are met:5//6// * Redistributions of source code must retain the above copyright notice,7// this list of conditions and the following disclaimer.8// * Redistributions in binary form must reproduce the above copyright9// notice, this list of conditions and the following disclaimer in the10// documentation and/or other materials provided with the distribution.11// * Neither the name of ARM Limited nor the names of its contributors may12// be used to endorse or promote products derived from this software13// without specific prior written permission.14//15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND16// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE19// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR20// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF21// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS22// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN23// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)24// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE25// POSSIBILITY OF SUCH DAMAGE.2627extern "C" {28#include <inttypes.h>29#include <stdint.h>30}3132#include <cassert>33#include <cmath>34#include <cstdio>35#include <cstdlib>36#include <cstring>37#include <iomanip>38#include <iostream>3940#include "utils-vixl.h"41#include "aarch32/constants-aarch32.h"42#include "aarch32/instructions-aarch32.h"43#include "aarch32/operands-aarch32.h"4445namespace vixl {46namespace aarch32 {4748// Operand4950std::ostream& operator<<(std::ostream& os, const Operand& operand) {51if (operand.IsImmediate()) {52return os << "#" << operand.GetImmediate();53}54if (operand.IsImmediateShiftedRegister()) {55if ((operand.GetShift().IsLSL() || operand.GetShift().IsROR()) &&56(operand.GetShiftAmount() == 0)) {57return os << operand.GetBaseRegister();58}59if (operand.GetShift().IsRRX()) {60return os << operand.GetBaseRegister() << ", rrx";61}62return os << operand.GetBaseRegister() << ", " << operand.GetShift() << " #"63<< operand.GetShiftAmount();64}65if (operand.IsRegisterShiftedRegister()) {66return os << operand.GetBaseRegister() << ", " << operand.GetShift() << " "67<< operand.GetShiftRegister();68}69VIXL_UNREACHABLE();70return os;71}7273std::ostream& operator<<(std::ostream& os, const NeonImmediate& neon_imm) {74if (neon_imm.IsDouble()) {75if (neon_imm.imm_.d_ == 0) {76if (copysign(1.0, neon_imm.imm_.d_) < 0.0) {77return os << "#-0.0";78}79return os << "#0.0";80}81return os << "#" << std::setprecision(9) << neon_imm.imm_.d_;82}83if (neon_imm.IsFloat()) {84if (neon_imm.imm_.f_ == 0) {85if (copysign(1.0, neon_imm.imm_.d_) < 0.0) return os << "#-0.0";86return os << "#0.0";87}88return os << "#" << std::setprecision(9) << neon_imm.imm_.f_;89}90if (neon_imm.IsInteger64()) {91return os << "#0x" << std::hex << std::setw(16) << std::setfill('0')92<< neon_imm.imm_.u64_ << std::dec;93}94return os << "#" << neon_imm.imm_.u32_;95}9697// SOperand9899std::ostream& operator<<(std::ostream& os, const SOperand& operand) {100if (operand.IsImmediate()) {101return os << operand.GetNeonImmediate();102}103return os << operand.GetRegister();104}105106// DOperand107108std::ostream& operator<<(std::ostream& os, const DOperand& operand) {109if (operand.IsImmediate()) {110return os << operand.GetNeonImmediate();111}112return os << operand.GetRegister();113}114115// QOperand116117std::ostream& operator<<(std::ostream& os, const QOperand& operand) {118if (operand.IsImmediate()) {119return os << operand.GetNeonImmediate();120}121return os << operand.GetRegister();122}123124125ImmediateVbic::ImmediateVbic(DataType dt, const NeonImmediate& neon_imm) {126if (neon_imm.IsInteger32()) {127uint32_t immediate = neon_imm.GetImmediate<uint32_t>();128if (dt.GetValue() == I16) {129if ((immediate & ~0xff) == 0) {130SetEncodingValue(0x9);131SetEncodedImmediate(immediate);132} else if ((immediate & ~0xff00) == 0) {133SetEncodingValue(0xb);134SetEncodedImmediate(immediate >> 8);135}136} else if (dt.GetValue() == I32) {137if ((immediate & ~0xff) == 0) {138SetEncodingValue(0x1);139SetEncodedImmediate(immediate);140} else if ((immediate & ~0xff00) == 0) {141SetEncodingValue(0x3);142SetEncodedImmediate(immediate >> 8);143} else if ((immediate & ~0xff0000) == 0) {144SetEncodingValue(0x5);145SetEncodedImmediate(immediate >> 16);146} else if ((immediate & ~0xff000000) == 0) {147SetEncodingValue(0x7);148SetEncodedImmediate(immediate >> 24);149}150}151}152}153154155DataType ImmediateVbic::DecodeDt(uint32_t cmode) {156switch (cmode) {157case 0x1:158case 0x3:159case 0x5:160case 0x7:161return I32;162case 0x9:163case 0xb:164return I16;165default:166break;167}168VIXL_UNREACHABLE();169return kDataTypeValueInvalid;170}171172173NeonImmediate ImmediateVbic::DecodeImmediate(uint32_t cmode,174uint32_t immediate) {175switch (cmode) {176case 0x1:177case 0x9:178return immediate;179case 0x3:180case 0xb:181return immediate << 8;182case 0x5:183return immediate << 16;184case 0x7:185return immediate << 24;186default:187break;188}189VIXL_UNREACHABLE();190return 0;191}192193194ImmediateVmov::ImmediateVmov(DataType dt, const NeonImmediate& neon_imm) {195if (neon_imm.IsInteger()) {196switch (dt.GetValue()) {197case I8:198if (neon_imm.CanConvert<uint8_t>()) {199SetEncodingValue(0xe);200SetEncodedImmediate(neon_imm.GetImmediate<uint8_t>());201}202break;203case I16:204if (neon_imm.IsInteger32()) {205uint32_t immediate = neon_imm.GetImmediate<uint32_t>();206if ((immediate & ~0xff) == 0) {207SetEncodingValue(0x8);208SetEncodedImmediate(immediate);209} else if ((immediate & ~0xff00) == 0) {210SetEncodingValue(0xa);211SetEncodedImmediate(immediate >> 8);212}213}214break;215case I32:216if (neon_imm.IsInteger32()) {217uint32_t immediate = neon_imm.GetImmediate<uint32_t>();218if ((immediate & ~0xff) == 0) {219SetEncodingValue(0x0);220SetEncodedImmediate(immediate);221} else if ((immediate & ~0xff00) == 0) {222SetEncodingValue(0x2);223SetEncodedImmediate(immediate >> 8);224} else if ((immediate & ~0xff0000) == 0) {225SetEncodingValue(0x4);226SetEncodedImmediate(immediate >> 16);227} else if ((immediate & ~0xff000000) == 0) {228SetEncodingValue(0x6);229SetEncodedImmediate(immediate >> 24);230} else if ((immediate & ~0xff00) == 0xff) {231SetEncodingValue(0xc);232SetEncodedImmediate(immediate >> 8);233} else if ((immediate & ~0xff0000) == 0xffff) {234SetEncodingValue(0xd);235SetEncodedImmediate(immediate >> 16);236}237}238break;239case I64: {240bool is_valid = true;241uint32_t encoding = 0;242if (neon_imm.IsInteger32()) {243uint32_t immediate = neon_imm.GetImmediate<uint32_t>();244uint32_t mask = 0xff000000;245for (uint32_t set_bit = 1 << 3; set_bit != 0; set_bit >>= 1) {246if ((immediate & mask) == mask) {247encoding |= set_bit;248} else if ((immediate & mask) != 0) {249is_valid = false;250break;251}252mask >>= 8;253}254} else {255uint64_t immediate = neon_imm.GetImmediate<uint64_t>();256uint64_t mask = UINT64_C(0xff) << 56;257for (uint32_t set_bit = 1 << 7; set_bit != 0; set_bit >>= 1) {258if ((immediate & mask) == mask) {259encoding |= set_bit;260} else if ((immediate & mask) != 0) {261is_valid = false;262break;263}264mask >>= 8;265}266}267if (is_valid) {268SetEncodingValue(0x1e);269SetEncodedImmediate(encoding);270}271break;272}273default:274break;275}276} else {277switch (dt.GetValue()) {278case F32:279if (neon_imm.IsFloat() || neon_imm.IsDouble()) {280ImmediateVFP vfp(neon_imm.GetImmediate<float>());281if (vfp.IsValid()) {282SetEncodingValue(0xf);283SetEncodedImmediate(vfp.GetEncodingValue());284}285}286break;287default:288break;289}290}291}292293294DataType ImmediateVmov::DecodeDt(uint32_t cmode) {295switch (cmode & 0xf) {296case 0x0:297case 0x2:298case 0x4:299case 0x6:300case 0xc:301case 0xd:302return I32;303case 0x8:304case 0xa:305return I16;306case 0xe:307return ((cmode & 0x10) == 0) ? I8 : I64;308case 0xf:309if ((cmode & 0x10) == 0) return F32;310break;311default:312break;313}314VIXL_UNREACHABLE();315return kDataTypeValueInvalid;316}317318319NeonImmediate ImmediateVmov::DecodeImmediate(uint32_t cmode,320uint32_t immediate) {321switch (cmode & 0xf) {322case 0x8:323case 0x0:324return immediate;325case 0x2:326case 0xa:327return immediate << 8;328case 0x4:329return immediate << 16;330case 0x6:331return immediate << 24;332case 0xc:333return (immediate << 8) | 0xff;334case 0xd:335return (immediate << 16) | 0xffff;336case 0xe: {337if (cmode == 0x1e) {338uint64_t encoding = 0;339for (uint32_t set_bit = 1 << 7; set_bit != 0; set_bit >>= 1) {340encoding <<= 8;341if ((immediate & set_bit) != 0) {342encoding |= 0xff;343}344}345return encoding;346} else {347return immediate;348}349}350case 0xf: {351return ImmediateVFP::Decode<float>(immediate);352}353default:354break;355}356VIXL_UNREACHABLE();357return 0;358}359360361ImmediateVmvn::ImmediateVmvn(DataType dt, const NeonImmediate& neon_imm) {362if (neon_imm.IsInteger32()) {363uint32_t immediate = neon_imm.GetImmediate<uint32_t>();364switch (dt.GetValue()) {365case I16:366if ((immediate & ~0xff) == 0) {367SetEncodingValue(0x8);368SetEncodedImmediate(immediate);369} else if ((immediate & ~0xff00) == 0) {370SetEncodingValue(0xa);371SetEncodedImmediate(immediate >> 8);372}373break;374case I32:375if ((immediate & ~0xff) == 0) {376SetEncodingValue(0x0);377SetEncodedImmediate(immediate);378} else if ((immediate & ~0xff00) == 0) {379SetEncodingValue(0x2);380SetEncodedImmediate(immediate >> 8);381} else if ((immediate & ~0xff0000) == 0) {382SetEncodingValue(0x4);383SetEncodedImmediate(immediate >> 16);384} else if ((immediate & ~0xff000000) == 0) {385SetEncodingValue(0x6);386SetEncodedImmediate(immediate >> 24);387} else if ((immediate & ~0xff00) == 0xff) {388SetEncodingValue(0xc);389SetEncodedImmediate(immediate >> 8);390} else if ((immediate & ~0xff0000) == 0xffff) {391SetEncodingValue(0xd);392SetEncodedImmediate(immediate >> 16);393}394break;395default:396break;397}398}399}400401402DataType ImmediateVmvn::DecodeDt(uint32_t cmode) {403switch (cmode) {404case 0x0:405case 0x2:406case 0x4:407case 0x6:408case 0xc:409case 0xd:410return I32;411case 0x8:412case 0xa:413return I16;414default:415break;416}417VIXL_UNREACHABLE();418return kDataTypeValueInvalid;419}420421422NeonImmediate ImmediateVmvn::DecodeImmediate(uint32_t cmode,423uint32_t immediate) {424switch (cmode) {425case 0x0:426case 0x8:427return immediate;428case 0x2:429case 0xa:430return immediate << 8;431case 0x4:432return immediate << 16;433case 0x6:434return immediate << 24;435case 0xc:436return (immediate << 8) | 0xff;437case 0xd:438return (immediate << 16) | 0xffff;439default:440break;441}442VIXL_UNREACHABLE();443return 0;444}445446447ImmediateVorr::ImmediateVorr(DataType dt, const NeonImmediate& neon_imm) {448if (neon_imm.IsInteger32()) {449uint32_t immediate = neon_imm.GetImmediate<uint32_t>();450if (dt.GetValue() == I16) {451if ((immediate & ~0xff) == 0) {452SetEncodingValue(0x9);453SetEncodedImmediate(immediate);454} else if ((immediate & ~0xff00) == 0) {455SetEncodingValue(0xb);456SetEncodedImmediate(immediate >> 8);457}458} else if (dt.GetValue() == I32) {459if ((immediate & ~0xff) == 0) {460SetEncodingValue(0x1);461SetEncodedImmediate(immediate);462} else if ((immediate & ~0xff00) == 0) {463SetEncodingValue(0x3);464SetEncodedImmediate(immediate >> 8);465} else if ((immediate & ~0xff0000) == 0) {466SetEncodingValue(0x5);467SetEncodedImmediate(immediate >> 16);468} else if ((immediate & ~0xff000000) == 0) {469SetEncodingValue(0x7);470SetEncodedImmediate(immediate >> 24);471}472}473}474}475476477DataType ImmediateVorr::DecodeDt(uint32_t cmode) {478switch (cmode) {479case 0x1:480case 0x3:481case 0x5:482case 0x7:483return I32;484case 0x9:485case 0xb:486return I16;487default:488break;489}490VIXL_UNREACHABLE();491return kDataTypeValueInvalid;492}493494495NeonImmediate ImmediateVorr::DecodeImmediate(uint32_t cmode,496uint32_t immediate) {497switch (cmode) {498case 0x1:499case 0x9:500return immediate;501case 0x3:502case 0xb:503return immediate << 8;504case 0x5:505return immediate << 16;506case 0x7:507return immediate << 24;508default:509break;510}511VIXL_UNREACHABLE();512return 0;513}514515// MemOperand516517std::ostream& operator<<(std::ostream& os, const MemOperand& operand) {518os << "[" << operand.GetBaseRegister();519if (operand.GetAddrMode() == PostIndex) {520os << "]";521if (operand.IsRegisterOnly()) return os << "!";522}523if (operand.IsImmediate()) {524if ((operand.GetOffsetImmediate() != 0) || operand.GetSign().IsMinus() ||525((operand.GetAddrMode() != Offset) && !operand.IsRegisterOnly())) {526if (operand.GetOffsetImmediate() == 0) {527os << ", #" << operand.GetSign() << operand.GetOffsetImmediate();528} else {529os << ", #" << operand.GetOffsetImmediate();530}531}532} else if (operand.IsPlainRegister()) {533os << ", " << operand.GetSign() << operand.GetOffsetRegister();534} else if (operand.IsShiftedRegister()) {535os << ", " << operand.GetSign() << operand.GetOffsetRegister()536<< ImmediateShiftOperand(operand.GetShift(), operand.GetShiftAmount());537} else {538VIXL_UNREACHABLE();539return os;540}541if (operand.GetAddrMode() == Offset) {542os << "]";543} else if (operand.GetAddrMode() == PreIndex) {544os << "]!";545}546return os;547}548549std::ostream& operator<<(std::ostream& os, const AlignedMemOperand& operand) {550os << "[" << operand.GetBaseRegister() << operand.GetAlignment() << "]";551if (operand.GetAddrMode() == PostIndex) {552if (operand.IsPlainRegister()) {553os << ", " << operand.GetOffsetRegister();554} else {555os << "!";556}557}558return os;559}560561} // namespace aarch32562} // namespace vixl563564565