Path: blob/master/dep/vixl/src/aarch32/instructions-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 copyright notice,9// this list of conditions and the following disclaimer in the documentation10// and/or other materials provided with the distribution.11// * Neither the name of ARM Limited nor the names of its contributors may be12// used to endorse or promote products derived from this software without13// 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, THE IMPLIED17// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE18// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE19// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR21// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER22// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,23// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE24// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.2526extern "C" {27#include <stdint.h>28}2930#include <cassert>31#include <cstdio>32#include <cstdlib>33#include <cstring>34#include <iostream>3536#include "utils-vixl.h"37#include "aarch32/constants-aarch32.h"38#include "aarch32/instructions-aarch32.h"3940namespace vixl {41namespace aarch32 {424344bool Shift::IsValidAmount(uint32_t amount) const {45switch (GetType()) {46case LSL:47return amount <= 31;48case ROR:49return (amount > 0) && (amount <= 31);50case LSR:51case ASR:52return (amount > 0) && (amount <= 32);53case RRX:54return amount == 0;55default:56VIXL_UNREACHABLE();57return false;58}59}606162std::ostream& operator<<(std::ostream& os, const Register reg) {63switch (reg.GetCode()) {64case 12:65return os << "ip";66case 13:67return os << "sp";68case 14:69return os << "lr";70case 15:71return os << "pc";72default:73return os << "r" << reg.GetCode();74}75}767778SRegister VRegister::S() const {79VIXL_ASSERT(GetType() == kSRegister);80return SRegister(GetCode());81}828384DRegister VRegister::D() const {85VIXL_ASSERT(GetType() == kDRegister);86return DRegister(GetCode());87}888990QRegister VRegister::Q() const {91VIXL_ASSERT(GetType() == kQRegister);92return QRegister(GetCode());93}949596Register RegisterList::GetFirstAvailableRegister() const {97if (list_ == 0) {98return Register();99}100return Register(CountTrailingZeros(list_));101}102103104std::ostream& PrintRegisterList(std::ostream& os, // NOLINT(runtime/references)105uint32_t list) {106os << "{";107bool first = true;108int code = 0;109while (list != 0) {110if ((list & 1) != 0) {111if (first) {112first = false;113} else {114os << ",";115}116os << Register(code);117}118list >>= 1;119code++;120}121os << "}";122return os;123}124125126std::ostream& operator<<(std::ostream& os, RegisterList registers) {127return PrintRegisterList(os, registers.GetList());128}129130131QRegister VRegisterList::GetFirstAvailableQRegister() const {132for (uint32_t i = 0; i < kNumberOfQRegisters; i++) {133if (((list_ >> (i * 4)) & 0xf) == 0xf) return QRegister(i);134}135return QRegister();136}137138139DRegister VRegisterList::GetFirstAvailableDRegister() const {140for (uint32_t i = 0; i < kMaxNumberOfDRegisters; i++) {141if (((list_ >> (i * 2)) & 0x3) == 0x3) return DRegister(i);142}143return DRegister();144}145146147SRegister VRegisterList::GetFirstAvailableSRegister() const {148for (uint32_t i = 0; i < kNumberOfSRegisters; i++) {149if (((list_ >> i) & 0x1) != 0) return SRegister(i);150}151return SRegister();152}153154155std::ostream& operator<<(std::ostream& os, SRegisterList reglist) {156SRegister first = reglist.GetFirstSRegister();157SRegister last = reglist.GetLastSRegister();158if (first.Is(last))159os << "{" << first << "}";160else161os << "{" << first << "-" << last << "}";162return os;163}164165166std::ostream& operator<<(std::ostream& os, DRegisterList reglist) {167DRegister first = reglist.GetFirstDRegister();168DRegister last = reglist.GetLastDRegister();169if (first.Is(last))170os << "{" << first << "}";171else172os << "{" << first << "-" << last << "}";173return os;174}175176std::ostream& operator<<(std::ostream& os, NeonRegisterList nreglist) {177DRegister first = nreglist.GetFirstDRegister();178int increment = nreglist.IsSingleSpaced() ? 1 : 2;179int count =180nreglist.GetLastDRegister().GetCode() - first.GetCode() + increment;181if (count < 0) count += kMaxNumberOfDRegisters;182os << "{";183bool first_displayed = false;184for (;;) {185if (first_displayed) {186os << ",";187} else {188first_displayed = true;189}190os << first;191if (nreglist.IsTransferOneLane()) {192os << "[" << nreglist.GetTransferLane() << "]";193} else if (nreglist.IsTransferAllLanes()) {194os << "[]";195}196count -= increment;197if (count <= 0) break;198unsigned next = first.GetCode() + increment;199if (next >= kMaxNumberOfDRegisters) next -= kMaxNumberOfDRegisters;200first = DRegister(next);201}202os << "}";203return os;204}205206207const char* SpecialRegister::GetName() const {208switch (reg_) {209case APSR:210return "APSR";211case SPSR:212return "SPSR";213}214VIXL_UNREACHABLE();215return "??";216}217218219const char* MaskedSpecialRegister::GetName() const {220switch (reg_) {221case APSR_nzcvq:222return "APSR_nzcvq";223case APSR_g:224return "APSR_g";225case APSR_nzcvqg:226return "APSR_nzcvqg";227case CPSR_c:228return "CPSR_c";229case CPSR_x:230return "CPSR_x";231case CPSR_xc:232return "CPSR_xc";233case CPSR_sc:234return "CPSR_sc";235case CPSR_sx:236return "CPSR_sx";237case CPSR_sxc:238return "CPSR_sxc";239case CPSR_fc:240return "CPSR_fc";241case CPSR_fx:242return "CPSR_fx";243case CPSR_fxc:244return "CPSR_fxc";245case CPSR_fsc:246return "CPSR_fsc";247case CPSR_fsx:248return "CPSR_fsx";249case CPSR_fsxc:250return "CPSR_fsxc";251case SPSR_c:252return "SPSR_c";253case SPSR_x:254return "SPSR_x";255case SPSR_xc:256return "SPSR_xc";257case SPSR_s:258return "SPSR_s";259case SPSR_sc:260return "SPSR_sc";261case SPSR_sx:262return "SPSR_sx";263case SPSR_sxc:264return "SPSR_sxc";265case SPSR_f:266return "SPSR_f";267case SPSR_fc:268return "SPSR_fc";269case SPSR_fx:270return "SPSR_fx";271case SPSR_fxc:272return "SPSR_fxc";273case SPSR_fs:274return "SPSR_fs";275case SPSR_fsc:276return "SPSR_fsc";277case SPSR_fsx:278return "SPSR_fsx";279case SPSR_fsxc:280return "SPSR_fsxc";281}282VIXL_UNREACHABLE();283return "??";284}285286287const char* BankedRegister::GetName() const {288switch (reg_) {289case R8_usr:290return "R8_usr";291case R9_usr:292return "R9_usr";293case R10_usr:294return "R10_usr";295case R11_usr:296return "R11_usr";297case R12_usr:298return "R12_usr";299case SP_usr:300return "SP_usr";301case LR_usr:302return "LR_usr";303case R8_fiq:304return "R8_fiq";305case R9_fiq:306return "R9_fiq";307case R10_fiq:308return "R10_fiq";309case R11_fiq:310return "R11_fiq";311case R12_fiq:312return "R12_fiq";313case SP_fiq:314return "SP_fiq";315case LR_fiq:316return "LR_fiq";317case LR_irq:318return "LR_irq";319case SP_irq:320return "SP_irq";321case LR_svc:322return "LR_svc";323case SP_svc:324return "SP_svc";325case LR_abt:326return "LR_abt";327case SP_abt:328return "SP_abt";329case LR_und:330return "LR_und";331case SP_und:332return "SP_und";333case LR_mon:334return "LR_mon";335case SP_mon:336return "SP_mon";337case ELR_hyp:338return "ELR_hyp";339case SP_hyp:340return "SP_hyp";341case SPSR_fiq:342return "SPSR_fiq";343case SPSR_irq:344return "SPSR_irq";345case SPSR_svc:346return "SPSR_svc";347case SPSR_abt:348return "SPSR_abt";349case SPSR_und:350return "SPSR_und";351case SPSR_mon:352return "SPSR_mon";353case SPSR_hyp:354return "SPSR_hyp";355}356VIXL_UNREACHABLE();357return "??";358}359360const char* SpecialFPRegister::GetName() const {361switch (reg_) {362case FPSID:363return "FPSID";364case FPSCR:365return "FPSCR";366case MVFR2:367return "MVFR2";368case MVFR1:369return "MVFR1";370case MVFR0:371return "MVFR0";372case FPEXC:373return "FPEXC";374}375VIXL_UNREACHABLE();376return "??";377}378379380const char* Condition::GetName() const {381switch (condition_) {382case eq:383return "eq";384case ne:385return "ne";386case cs:387return "cs";388case cc:389return "cc";390case mi:391return "mi";392case pl:393return "pl";394case vs:395return "vs";396case vc:397return "vc";398case hi:399return "hi";400case ls:401return "ls";402case ge:403return "ge";404case lt:405return "lt";406case gt:407return "gt";408case le:409return "le";410case al:411return "";412case Condition::kNone:413return "";414}415return "<und>";416}417418419const char* Shift::GetName() const {420switch (shift_) {421case LSL:422return "lsl";423case LSR:424return "lsr";425case ASR:426return "asr";427case ROR:428return "ror";429case RRX:430return "rrx";431}432VIXL_UNREACHABLE();433return "??";434}435436437const char* EncodingSize::GetName() const {438switch (size_) {439case Best:440case Narrow:441return "";442case Wide:443return ".w";444}445VIXL_UNREACHABLE();446return "??";447}448449450const char* DataType::GetName() const {451switch (value_) {452case kDataTypeValueInvalid:453return ".??";454case kDataTypeValueNone:455return "";456case S8:457return ".s8";458case S16:459return ".s16";460case S32:461return ".s32";462case S64:463return ".s64";464case U8:465return ".u8";466case U16:467return ".u16";468case U32:469return ".u32";470case U64:471return ".u64";472case F16:473return ".f16";474case F32:475return ".f32";476case F64:477return ".f64";478case I8:479return ".i8";480case I16:481return ".i16";482case I32:483return ".i32";484case I64:485return ".i64";486case P8:487return ".p8";488case P64:489return ".p64";490case Untyped8:491return ".8";492case Untyped16:493return ".16";494case Untyped32:495return ".32";496case Untyped64:497return ".64";498}499VIXL_UNREACHABLE();500return ".??";501}502503504const char* MemoryBarrier::GetName() const {505switch (type_) {506case OSHLD:507return "oshld";508case OSHST:509return "oshst";510case OSH:511return "osh";512case NSHLD:513return "nshld";514case NSHST:515return "nshst";516case NSH:517return "nsh";518case ISHLD:519return "ishld";520case ISHST:521return "ishst";522case ISH:523return "ish";524case LD:525return "ld";526case ST:527return "st";528case SY:529return "sy";530}531switch (static_cast<int>(type_)) {532case 0:533return "#0x0";534case 4:535return "#0x4";536case 8:537return "#0x8";538case 0xc:539return "#0xc";540}541VIXL_UNREACHABLE();542return "??";543}544545546const char* InterruptFlags::GetName() const {547switch (type_) {548case F:549return "f";550case I:551return "i";552case IF:553return "if";554case A:555return "a";556case AF:557return "af";558case AI:559return "ai";560case AIF:561return "aif";562}563VIXL_ASSERT(type_ == 0);564return "";565}566567568const char* Endianness::GetName() const {569switch (type_) {570case LE:571return "le";572case BE:573return "be";574}575VIXL_UNREACHABLE();576return "??";577}578579580// Constructor used for disassembly.581ImmediateShiftOperand::ImmediateShiftOperand(int shift_value, int amount_value)582: Shift(shift_value) {583switch (shift_value) {584case LSL:585amount_ = amount_value;586break;587case LSR:588case ASR:589amount_ = (amount_value == 0) ? 32 : amount_value;590break;591case ROR:592amount_ = amount_value;593if (amount_value == 0) SetType(RRX);594break;595default:596VIXL_UNREACHABLE();597SetType(LSL);598amount_ = 0;599break;600}601}602603604ImmediateT32::ImmediateT32(uint32_t imm) {605// 00000000 00000000 00000000 abcdefgh606if ((imm & ~0xff) == 0) {607SetEncodingValue(imm);608return;609}610if ((imm >> 16) == (imm & 0xffff)) {611if ((imm & 0xff00) == 0) {612// 00000000 abcdefgh 00000000 abcdefgh613SetEncodingValue((imm & 0xff) | (0x1 << 8));614return;615}616if ((imm & 0xff) == 0) {617// abcdefgh 00000000 abcdefgh 00000000618SetEncodingValue(((imm >> 8) & 0xff) | (0x2 << 8));619return;620}621if (((imm >> 8) & 0xff) == (imm & 0xff)) {622// abcdefgh abcdefgh abcdefgh abcdefgh623SetEncodingValue((imm & 0xff) | (0x3 << 8));624return;625}626}627for (int shift = 0; shift < 24; shift++) {628uint32_t imm8 = imm >> (24 - shift);629uint32_t overflow = imm << (8 + shift);630if ((imm8 <= 0xff) && ((imm8 & 0x80) != 0) && (overflow == 0)) {631SetEncodingValue(((shift + 8) << 7) | (imm8 & 0x7F));632return;633}634}635}636637638static inline uint32_t ror(uint32_t x, int i) {639VIXL_ASSERT((0 < i) && (i < 32));640return (x >> i) | (x << (32 - i));641}642643644bool ImmediateT32::IsImmediateT32(uint32_t imm) {645/* abcdefgh abcdefgh abcdefgh abcdefgh */646if ((imm ^ ror(imm, 8)) == 0) return true;647/* 00000000 abcdefgh 00000000 abcdefgh */648/* abcdefgh 00000000 abcdefgh 00000000 */649if ((imm ^ ror(imm, 16)) == 0 &&650(((imm & 0xff00) == 0) || ((imm & 0xff) == 0)))651return true;652/* isolate least-significant set bit */653uint32_t lsb = imm & UnsignedNegate(imm);654/* if imm is less than lsb*256 then it fits, but instead we test imm/256 to655* avoid overflow (underflow is always a successful case) */656return ((imm >> 8) < lsb);657}658659660uint32_t ImmediateT32::Decode(uint32_t value) {661uint32_t base = value & 0xff;662switch (value >> 8) {663case 0:664return base;665case 1:666return base | (base << 16);667case 2:668return (base << 8) | (base << 24);669case 3:670return base | (base << 8) | (base << 16) | (base << 24);671default:672base |= 0x80;673return base << (32 - (value >> 7));674}675}676677678ImmediateA32::ImmediateA32(uint32_t imm) {679// Deal with rot = 0 first to avoid undefined shift by 32.680if (imm <= 0xff) {681SetEncodingValue(imm);682return;683}684for (int rot = 2; rot < 32; rot += 2) {685uint32_t imm8 = (imm << rot) | (imm >> (32 - rot));686if (imm8 <= 0xff) {687SetEncodingValue((rot << 7) | imm8);688return;689}690}691}692693694bool ImmediateA32::IsImmediateA32(uint32_t imm) {695/* fast-out */696if (imm < 256) return true;697/* avoid getting confused by wrapped-around bytes (this transform has no698* effect on pass/fail results) */699if (imm & 0xff000000) imm = ror(imm, 16);700/* copy odd-numbered set bits into even-numbered bits immediately below, so701* that the least-significant set bit is always an even bit */702imm = imm | ((imm >> 1) & 0x55555555);703/* isolate least-significant set bit (always even) */704uint32_t lsb = imm & UnsignedNegate(imm);705/* if imm is less than lsb*256 then it fits, but instead we test imm/256 to706* avoid overflow (underflow is always a successful case) */707return ((imm >> 8) < lsb);708}709710711uint32_t ImmediateA32::Decode(uint32_t value) {712int rotation = (value >> 8) * 2;713VIXL_ASSERT(rotation >= 0);714VIXL_ASSERT(rotation <= 30);715value &= 0xff;716if (rotation == 0) return value;717return (value >> rotation) | (value << (32 - rotation));718}719720721uint32_t TypeEncodingValue(Shift shift) {722return shift.IsRRX() ? kRRXEncodedValue : shift.GetValue();723}724725726uint32_t AmountEncodingValue(Shift shift, uint32_t amount) {727switch (shift.GetType()) {728case LSL:729case ROR:730return amount;731case LSR:732case ASR:733return amount % 32;734case RRX:735return 0;736}737return 0;738}739740} // namespace aarch32741} // namespace vixl742743744