A64: Implement logical

This commit is contained in:
MerryMage 2018-01-07 12:52:12 +00:00
parent 5a1d88c5dc
commit 0641445e51
13 changed files with 499 additions and 26 deletions

View file

@ -40,10 +40,10 @@ std::vector<Matcher<V>> GetDecodeTable() {
INST(&V::SUBS_imm, "SUBS (immediate)", "z1110001ssiiiiiiiiiiiinnnnnddddd"),
// Data processing - Immediate - Logical
//INST(&V::AND_imm, "AND (immediate)", "z00100100Nrrrrrrssssssnnnnnddddd"),
//INST(&V::ORR_imm, "ORR (immediate)", "z01100100Nrrrrrrssssssnnnnnddddd"),
//INST(&V::EOR_imm, "EOR (immediate)", "z10100100Nrrrrrrssssssnnnnnddddd"),
//INST(&V::ANDS_imm, "ANDS (immediate)", "z11100100Nrrrrrrssssssnnnnnddddd"),
INST(&V::AND_imm, "AND (immediate)", "z00100100Nrrrrrrssssssnnnnnddddd"),
INST(&V::ORR_imm, "ORR (immediate)", "z01100100Nrrrrrrssssssnnnnnddddd"),
INST(&V::EOR_imm, "EOR (immediate)", "z10100100Nrrrrrrssssssnnnnnddddd"),
INST(&V::ANDS_imm, "ANDS (immediate)", "z11100100Nrrrrrrssssssnnnnnddddd"),
// Data processing - Immediate - Move Wide
//INST(&V::MOVN, "MOVN", "z00100101ssiiiiiiiiiiiiiiiiddddd"),
@ -363,14 +363,14 @@ std::vector<Matcher<V>> GetDecodeTable() {
//INST(&V::AUTDB, "AUTDB, AUTDZB", "110110101100000100Z111nnnnnddddd"),
// Data Processing - Register - Logical (shifted register)
//INST(&V::AND_shift, "AND (shifted register)", "z0001010ss0mmmmmiiiiiinnnnnddddd"),
//INST(&V::BIC_shift, "BIC (shifted register)", "z0001010ss1mmmmmiiiiiinnnnnddddd"),
//INST(&V::ORR_shift, "ORR (shifted register)", "z0101010ss0mmmmmiiiiiinnnnnddddd"),
//INST(&V::ORN_shift, "ORN (shifted register)", "z0101010ss1mmmmmiiiiiinnnnnddddd"),
//INST(&V::EOR_shift, "EOR (shifted register)", "z1001010ss0mmmmmiiiiiinnnnnddddd"),
//INST(&V::EON, "EON (shifted register)", "z1001010ss1mmmmmiiiiiinnnnnddddd"),
//INST(&V::ANDS_shift, "ANDS (shifted register)", "z1101010ss0mmmmmiiiiiinnnnnddddd"),
//INST(&V::BICS, "BICS (shifted register)", "z1101010ss1mmmmmiiiiiinnnnnddddd"),
INST(&V::AND_shift, "AND (shifted register)", "z0001010ss0mmmmmiiiiiinnnnnddddd"),
INST(&V::BIC_shift, "BIC (shifted register)", "z0001010ss1mmmmmiiiiiinnnnnddddd"),
INST(&V::ORR_shift, "ORR (shifted register)", "z0101010ss0mmmmmiiiiiinnnnnddddd"),
INST(&V::ORN_shift, "ORN (shifted register)", "z0101010ss1mmmmmiiiiiinnnnnddddd"),
INST(&V::EOR_shift, "EOR (shifted register)", "z1001010ss0mmmmmiiiiiinnnnnddddd"),
INST(&V::EON, "EON (shifted register)", "z1001010ss1mmmmmiiiiiinnnnnddddd"),
INST(&V::ANDS_shift, "ANDS (shifted register)", "z1101010ss0mmmmmiiiiiinnnnnddddd"),
INST(&V::BICS, "BICS (shifted register)", "z1101010ss1mmmmmiiiiiinnnnnddddd"),
// Data Processing - Register - Add/Sub (shifted register)
INST(&V::ADD_shift, "ADD (shifted register)", "z0001011ss0mmmmmiiiiiinnnnnddddd"),

View file

@ -0,0 +1,216 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#include "frontend/A64/translate/impl/impl.h"
namespace Dynarmic {
namespace A64 {
bool TranslatorVisitor::AND_imm(bool sf, bool N, Imm<6> immr, Imm<6> imms, Reg Rn, Reg Rd) {
size_t datasize = sf ? 64 : 32;
if (!sf && N) return ReservedValue();
u64 imm;
if (auto masks = DecodeBitMasks(N, imms, immr, true)) {
imm = masks->wmask;
} else {
return ReservedValue();
}
auto operand1 = X(datasize, Rn);
auto result = ir.And(operand1, I(datasize, imm));
if (Rd == Reg::SP) {
SP(datasize, result);
} else {
X(datasize, Rd, result);
}
return true;
}
bool TranslatorVisitor::ORR_imm(bool sf, bool N, Imm<6> immr, Imm<6> imms, Reg Rn, Reg Rd) {
size_t datasize = sf ? 64 : 32;
if (!sf && N) return ReservedValue();
u64 imm;
if (auto masks = DecodeBitMasks(N, imms, immr, true)) {
imm = masks->wmask;
} else {
return ReservedValue();
}
auto operand1 = X(datasize, Rn);
auto result = ir.Or(operand1, I(datasize, imm));
if (Rd == Reg::SP) {
SP(datasize, result);
} else {
X(datasize, Rd, result);
}
return true;
}
bool TranslatorVisitor::EOR_imm(bool sf, bool N, Imm<6> immr, Imm<6> imms, Reg Rn, Reg Rd) {
size_t datasize = sf ? 64 : 32;
if (!sf && N) return ReservedValue();
u64 imm;
if (auto masks = DecodeBitMasks(N, imms, immr, true)) {
imm = masks->wmask;
} else {
return ReservedValue();
}
auto operand1 = X(datasize, Rn);
auto result = ir.Eor(operand1, I(datasize, imm));
if (Rd == Reg::SP) {
SP(datasize, result);
} else {
X(datasize, Rd, result);
}
return true;
}
bool TranslatorVisitor::ANDS_imm(bool sf, bool N, Imm<6> immr, Imm<6> imms, Reg Rn, Reg Rd) {
size_t datasize = sf ? 64 : 32;
if (!sf && N) return ReservedValue();
u64 imm;
if (auto masks = DecodeBitMasks(N, imms, immr, true)) {
imm = masks->wmask;
} else {
return ReservedValue();
}
auto operand1 = X(datasize, Rn);
auto result = ir.And(operand1, I(datasize, imm));
ir.SetNZCV(ir.NZCVFrom(result));
X(datasize, Rd, result);
return true;
}
bool TranslatorVisitor::AND_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
size_t datasize = sf ? 64 : 32;
if (!sf && imm6.Bit<5>()) return ReservedValue();
u8 shift_amount = imm6.ZeroExtend<u8>();
auto operand1 = X(datasize, Rn);
auto operand2 = ShiftReg(datasize, Rm, shift, ir.Imm8(shift_amount));
auto result = ir.And(operand1, operand2);
X(datasize, Rd, result);
return true;
}
bool TranslatorVisitor::BIC_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
size_t datasize = sf ? 64 : 32;
if (!sf && imm6.Bit<5>()) return ReservedValue();
u8 shift_amount = imm6.ZeroExtend<u8>();
auto operand1 = X(datasize, Rn);
auto operand2 = ShiftReg(datasize, Rm, shift, ir.Imm8(shift_amount));
operand2 = ir.Not(operand2);
auto result = ir.And(operand1, operand2);
X(datasize, Rd, result);
return true;
}
bool TranslatorVisitor::ORR_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
size_t datasize = sf ? 64 : 32;
if (!sf && imm6.Bit<5>()) return ReservedValue();
u8 shift_amount = imm6.ZeroExtend<u8>();
auto operand1 = X(datasize, Rn);
auto operand2 = ShiftReg(datasize, Rm, shift, ir.Imm8(shift_amount));
auto result = ir.Or(operand1, operand2);
X(datasize, Rd, result);
return true;
}
bool TranslatorVisitor::ORN_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
size_t datasize = sf ? 64 : 32;
if (!sf && imm6.Bit<5>()) return ReservedValue();
u8 shift_amount = imm6.ZeroExtend<u8>();
auto operand1 = X(datasize, Rn);
auto operand2 = ShiftReg(datasize, Rm, shift, ir.Imm8(shift_amount));
operand2 = ir.Not(operand2);
auto result = ir.Or(operand1, operand2);
X(datasize, Rd, result);
return true;
}
bool TranslatorVisitor::EOR_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
size_t datasize = sf ? 64 : 32;
if (!sf && imm6.Bit<5>()) return ReservedValue();
u8 shift_amount = imm6.ZeroExtend<u8>();
auto operand1 = X(datasize, Rn);
auto operand2 = ShiftReg(datasize, Rm, shift, ir.Imm8(shift_amount));
auto result = ir.Eor(operand1, operand2);
X(datasize, Rd, result);
return true;
}
bool TranslatorVisitor::EON(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
size_t datasize = sf ? 64 : 32;
if (!sf && imm6.Bit<5>()) return ReservedValue();
u8 shift_amount = imm6.ZeroExtend<u8>();
auto operand1 = X(datasize, Rn);
auto operand2 = ShiftReg(datasize, Rm, shift, ir.Imm8(shift_amount));
operand2 = ir.Not(operand2);
auto result = ir.Eor(operand1, operand2);
X(datasize, Rd, result);
return true;
}
bool TranslatorVisitor::ANDS_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
size_t datasize = sf ? 64 : 32;
if (!sf && imm6.Bit<5>()) return ReservedValue();
u8 shift_amount = imm6.ZeroExtend<u8>();
auto operand1 = X(datasize, Rn);
auto operand2 = ShiftReg(datasize, Rm, shift, ir.Imm8(shift_amount));
auto result = ir.And(operand1, operand2);
ir.SetNZCV(ir.NZCVFrom(result));
X(datasize, Rd, result);
return true;
}
bool TranslatorVisitor::BICS(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
size_t datasize = sf ? 64 : 32;
if (!sf && imm6.Bit<5>()) return ReservedValue();
u8 shift_amount = imm6.ZeroExtend<u8>();
auto operand1 = X(datasize, Rn);
auto operand2 = ShiftReg(datasize, Rm, shift, ir.Imm8(shift_amount));
operand2 = ir.Not(operand2);
auto result = ir.And(operand1, operand2);
ir.SetNZCV(ir.NZCVFrom(result));
X(datasize, Rd, result);
return true;
}
} // namespace A64
} // namespace Dynarmic

View file

@ -4,6 +4,7 @@
* General Public License version 2 or any later version.
*/
#include "common/bit_util.h"
#include "frontend/ir/terminal.h"
#include "frontend/A64/translate/impl/impl.h"
@ -25,6 +26,29 @@ bool TranslatorVisitor::ReservedValue() {
return false;
}
boost::optional<TranslatorVisitor::BitMasks> TranslatorVisitor::DecodeBitMasks(bool immN, Imm<6> imms, Imm<6> immr, bool immediate) {
int len = Common::HighestSetBit((immN ? 1 << 6 : 0) | (imms.ZeroExtend() ^ 0b111111));
if (len < 1)
return boost::none;
size_t levels = Common::Ones<size_t>(len);
if (immediate && (imms.ZeroExtend() & levels) == levels)
return boost::none;
s32 S = s32(imms.ZeroExtend() & levels);
s32 R = s32(immr.ZeroExtend() & levels);
u64 d = u64(S - R) & levels;
size_t esize = 1 << len;
u64 welem = Common::Ones<u64>(S + 1);
u64 telem = Common::Ones<u64>(d + 1);
u64 wmask = Common::RotateRight(Common::Replicate(welem, esize), R);
u64 tmask = Common::Replicate(telem, esize);
return BitMasks{wmask, tmask};
}
IR::U32U64 TranslatorVisitor::I(size_t bitsize, u64 value) {
switch (bitsize) {
case 32:

View file

@ -6,6 +6,8 @@
#pragma once
#include <boost/optional.hpp>
#include "frontend/A64/imm.h"
#include "frontend/A64/ir_emitter.h"
#include "frontend/A64/location_descriptor.h"
@ -25,6 +27,12 @@ struct TranslatorVisitor final {
bool UnpredictableInstruction();
bool ReservedValue();
struct BitMasks {
u64 wmask, tmask;
};
boost::optional<BitMasks> DecodeBitMasks(bool N, Imm<6> immr, Imm<6> imms, bool immediate);
IR::U32U64 I(size_t bitsize, u64 value);
IR::U32U64 X(size_t bitsize, Reg reg);
void X(size_t bitsize, Reg reg, IR::U32U64 value);