mirror of
https://git.suyu.dev/suyu/dynarmic.git
synced 2026-03-08 02:36:28 +00:00
A64: Implement addsub instructions
This commit is contained in:
@@ -34,10 +34,10 @@ std::vector<Matcher<V>> GetDecodeTable() {
|
||||
//INST(&V::ADRP, "ADRP", "1ii10000iiiiiiiiiiiiiiiiiiiddddd"),
|
||||
|
||||
// Data processing - Immediate - Add/Sub
|
||||
//INST(&V::ADD_imm, "ADD (immediate)", "z0010001ssiiiiiiiiiiiinnnnnddddd"),
|
||||
//INST(&V::ADDS_imm, "ADDS (immediate)", "z0110001ssiiiiiiiiiiiinnnnnddddd"),
|
||||
//INST(&V::SUB_imm, "SUB (immediate)", "z1010001ssiiiiiiiiiiiinnnnnddddd"),
|
||||
//INST(&V::SUBS_imm, "SUBS (immediate)", "z1110001ssiiiiiiiiiiiinnnnnddddd"),
|
||||
INST(&V::ADD_imm, "ADD (immediate)", "z0010001ssiiiiiiiiiiiinnnnnddddd"),
|
||||
INST(&V::ADDS_imm, "ADDS (immediate)", "z0110001ssiiiiiiiiiiiinnnnnddddd"),
|
||||
INST(&V::SUB_imm, "SUB (immediate)", "z1010001ssiiiiiiiiiiiinnnnnddddd"),
|
||||
INST(&V::SUBS_imm, "SUBS (immediate)", "z1110001ssiiiiiiiiiiiinnnnnddddd"),
|
||||
|
||||
// Data processing - Immediate - Logical
|
||||
//INST(&V::AND_imm, "AND (immediate)", "z00100100Nrrrrrrssssssnnnnnddddd"),
|
||||
@@ -374,21 +374,21 @@ std::vector<Matcher<V>> GetDecodeTable() {
|
||||
|
||||
// Data Processing - Register - Add/Sub (shifted register)
|
||||
INST(&V::ADD_shift, "ADD (shifted register)", "z0001011ss0mmmmmiiiiiinnnnnddddd"),
|
||||
//INST(&V::ADDS_shift, "ADDS (shifted register)", "z0101011ss0mmmmmiiiiiinnnnnddddd"),
|
||||
//INST(&V::SUB_shift, "SUB (shifted register)", "z1001011ss0mmmmmiiiiiinnnnnddddd"),
|
||||
//INST(&V::SUBS_shift, "SUBS (shifted register)", "z1101011ss0mmmmmiiiiiinnnnnddddd"),
|
||||
INST(&V::ADDS_shift, "ADDS (shifted register)", "z0101011ss0mmmmmiiiiiinnnnnddddd"),
|
||||
INST(&V::SUB_shift, "SUB (shifted register)", "z1001011ss0mmmmmiiiiiinnnnnddddd"),
|
||||
INST(&V::SUBS_shift, "SUBS (shifted register)", "z1101011ss0mmmmmiiiiiinnnnnddddd"),
|
||||
|
||||
// Data Processing - Register - Add/Sub (shifted register)
|
||||
//INST(&V::ADD_ext, "ADD (extended register)", "z0001011001mmmmmxxxiiinnnnnddddd"),
|
||||
//INST(&V::ADDS_ext, "ADDS (extended register)", "z0101011001mmmmmxxxiiinnnnnddddd"),
|
||||
//INST(&V::SUB_ext, "SUB (extended register)", "z1001011001mmmmmxxxiiinnnnnddddd"),
|
||||
//INST(&V::SUBS_ext, "SUBS (extended register)", "z1101011001mmmmmxxxiiinnnnnddddd"),
|
||||
INST(&V::ADD_ext, "ADD (extended register)", "z0001011001mmmmmxxxiiinnnnnddddd"),
|
||||
INST(&V::ADDS_ext, "ADDS (extended register)", "z0101011001mmmmmxxxiiinnnnnddddd"),
|
||||
INST(&V::SUB_ext, "SUB (extended register)", "z1001011001mmmmmxxxiiinnnnnddddd"),
|
||||
INST(&V::SUBS_ext, "SUBS (extended register)", "z1101011001mmmmmxxxiiinnnnnddddd"),
|
||||
|
||||
// Data Processing - Register - Add/Sub (with carry)
|
||||
//INST(&V::ADC, "ADC", "z0011010000mmmmm000000nnnnnddddd"),
|
||||
//INST(&V::ADCS, "ADCS", "z0111010000mmmmm000000nnnnnddddd"),
|
||||
//INST(&V::SBC, "SBC", "z1011010000mmmmm000000nnnnnddddd"),
|
||||
//INST(&V::SBCS, "SBCS", "z1111010000mmmmm000000nnnnnddddd"),
|
||||
INST(&V::ADC, "ADC", "z0011010000mmmmm000000nnnnnddddd"),
|
||||
INST(&V::ADCS, "ADCS", "z0111010000mmmmm000000nnnnnddddd"),
|
||||
INST(&V::SBC, "SBC", "z1011010000mmmmm000000nnnnnddddd"),
|
||||
INST(&V::SBCS, "SBCS", "z1111010000mmmmm000000nnnnnddddd"),
|
||||
|
||||
// Data Processing - Register - Conditional compare
|
||||
//INST(&V::CCMN_reg, "CCMN (register)", "z0111010010mmmmmcccc00nnnnn0ffff"),
|
||||
|
||||
@@ -22,21 +22,45 @@ u64 IREmitter::AlignPC(size_t alignment) {
|
||||
return static_cast<u64>(pc - pc % alignment);
|
||||
}
|
||||
|
||||
IR::U1 IREmitter::GetCFlag() {
|
||||
return Inst<IR::U1>(Opcode::A64GetCFlag);
|
||||
}
|
||||
|
||||
void IREmitter::SetNZCV(const IR::NZCV& nzcv) {
|
||||
Inst(Opcode::A64SetNZCV, nzcv);
|
||||
}
|
||||
|
||||
IR::U32 IREmitter::GetW(Reg reg) {
|
||||
if (reg == Reg::ZR)
|
||||
return Imm32(0);
|
||||
return Inst<IR::U32>(Opcode::A64GetW, IR::Value(reg));
|
||||
}
|
||||
|
||||
IR::U64 IREmitter::GetX(Reg reg) {
|
||||
if (reg == Reg::ZR)
|
||||
return Imm64(0);
|
||||
return Inst<IR::U64>(Opcode::A64GetX, IR::Value(reg));
|
||||
}
|
||||
|
||||
IR::U64 IREmitter::GetSP() {
|
||||
return Inst<IR::U64>(Opcode::A64GetSP);
|
||||
}
|
||||
|
||||
void IREmitter::SetW(const Reg reg, const IR::U32& value) {
|
||||
if (reg == Reg::ZR)
|
||||
return;
|
||||
Inst(Opcode::A64SetW, IR::Value(reg), value);
|
||||
}
|
||||
|
||||
void IREmitter::SetX(const Reg reg, const IR::U64& value) {
|
||||
if (reg == Reg::ZR)
|
||||
return;
|
||||
Inst(Opcode::A64SetX, IR::Value(reg), value);
|
||||
}
|
||||
|
||||
void IREmitter::SetSP(const IR::U64& value) {
|
||||
Inst(Opcode::A64SetSP, value);
|
||||
}
|
||||
|
||||
} // namespace IR
|
||||
} // namespace Dynarmic
|
||||
|
||||
@@ -31,10 +31,15 @@ public:
|
||||
u64 PC();
|
||||
u64 AlignPC(size_t alignment);
|
||||
|
||||
IR::U1 GetCFlag();
|
||||
void SetNZCV(const IR::NZCV& nzcv);
|
||||
|
||||
IR::U32 GetW(Reg source_reg);
|
||||
IR::U64 GetX(Reg source_reg);
|
||||
IR::U64 GetSP();
|
||||
void SetW(Reg dest_reg, const IR::U32& value);
|
||||
void SetX(Reg dest_reg, const IR::U64& value);
|
||||
void SetSP(const IR::U64& value);
|
||||
};
|
||||
|
||||
} // namespace IR
|
||||
|
||||
@@ -9,6 +9,114 @@
|
||||
namespace Dynarmic {
|
||||
namespace A64 {
|
||||
|
||||
bool TranslatorVisitor::ADD_imm(bool sf, Imm<2> shift, Imm<12> imm12, Reg Rn, Reg Rd) {
|
||||
size_t datasize = sf ? 64 : 32;
|
||||
|
||||
u64 imm;
|
||||
switch (shift.ZeroExtend()) {
|
||||
case 0b00:
|
||||
imm = imm12.ZeroExtend<u64>();
|
||||
break;
|
||||
case 0b01:
|
||||
imm = imm12.ZeroExtend<u64>() << 12;
|
||||
break;
|
||||
default:
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
auto operand1 = Rn == Reg::SP ? SP(datasize) : X(datasize, Rn);
|
||||
|
||||
auto result = ir.Add(operand1, I(datasize, imm));
|
||||
|
||||
if (Rd == Reg::SP) {
|
||||
SP(datasize, result);
|
||||
} else {
|
||||
X(datasize, Rd, result);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::ADDS_imm(bool sf, Imm<2> shift, Imm<12> imm12, Reg Rn, Reg Rd) {
|
||||
size_t datasize = sf ? 64 : 32;
|
||||
|
||||
u64 imm;
|
||||
switch (shift.ZeroExtend()) {
|
||||
case 0b00:
|
||||
imm = imm12.ZeroExtend<u64>();
|
||||
break;
|
||||
case 0b01:
|
||||
imm = imm12.ZeroExtend<u64>() << 12;
|
||||
break;
|
||||
default:
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
auto operand1 = Rn == Reg::SP ? SP(datasize) : X(datasize, Rn);
|
||||
|
||||
auto result = ir.Add(operand1, I(datasize, imm));
|
||||
|
||||
ir.SetNZCV(ir.NZCVFrom(result));
|
||||
|
||||
X(datasize, Rd, result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::SUB_imm(bool sf, Imm<2> shift, Imm<12> imm12, Reg Rn, Reg Rd) {
|
||||
size_t datasize = sf ? 64 : 32;
|
||||
|
||||
u64 imm;
|
||||
switch (shift.ZeroExtend()) {
|
||||
case 0b00:
|
||||
imm = imm12.ZeroExtend<u64>();
|
||||
break;
|
||||
case 0b01:
|
||||
imm = imm12.ZeroExtend<u64>() << 12;
|
||||
break;
|
||||
default:
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
auto operand1 = Rn == Reg::SP ? SP(datasize) : X(datasize, Rn);
|
||||
|
||||
auto result = ir.Sub(operand1, I(datasize, imm));
|
||||
|
||||
if (Rd == Reg::SP) {
|
||||
SP(datasize, result);
|
||||
} else {
|
||||
X(datasize, Rd, result);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::SUBS_imm(bool sf, Imm<2> shift, Imm<12> imm12, Reg Rn, Reg Rd) {
|
||||
size_t datasize = sf ? 64 : 32;
|
||||
|
||||
u64 imm;
|
||||
switch (shift.ZeroExtend()) {
|
||||
case 0b00:
|
||||
imm = imm12.ZeroExtend<u64>();
|
||||
break;
|
||||
case 0b01:
|
||||
imm = imm12.ZeroExtend<u64>() << 12;
|
||||
break;
|
||||
default:
|
||||
return ReservedValue();
|
||||
}
|
||||
|
||||
auto operand1 = Rn == Reg::SP ? SP(datasize) : X(datasize, Rn);
|
||||
|
||||
auto result = ir.Sub(operand1, I(datasize, imm));
|
||||
|
||||
ir.SetNZCV(ir.NZCVFrom(result));
|
||||
|
||||
X(datasize, Rd, result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::ADD_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
|
||||
size_t datasize = sf ? 64 : 32;
|
||||
|
||||
@@ -27,5 +135,199 @@ bool TranslatorVisitor::ADD_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Re
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::ADDS_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
|
||||
size_t datasize = sf ? 64 : 32;
|
||||
|
||||
if (shift == 0b11) return ReservedValue();
|
||||
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.Add(operand1, operand2);
|
||||
|
||||
ir.SetNZCV(ir.NZCVFrom(result));
|
||||
|
||||
X(datasize, Rd, result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::SUB_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
|
||||
size_t datasize = sf ? 64 : 32;
|
||||
|
||||
if (shift == 0b11) return ReservedValue();
|
||||
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.Sub(operand1, operand2);
|
||||
|
||||
X(datasize, Rd, result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::SUBS_shift(bool sf, Imm<2> shift, Reg Rm, Imm<6> imm6, Reg Rn, Reg Rd) {
|
||||
size_t datasize = sf ? 64 : 32;
|
||||
|
||||
if (shift == 0b11) return ReservedValue();
|
||||
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.Sub(operand1, operand2);
|
||||
|
||||
ir.SetNZCV(ir.NZCVFrom(result));
|
||||
|
||||
X(datasize, Rd, result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::ADD_ext(bool sf, Reg Rm, Imm<3> option, Imm<3> imm3, Reg Rn, Reg Rd) {
|
||||
size_t datasize = sf ? 64 : 32;
|
||||
u8 shift = imm3.ZeroExtend<u8>();
|
||||
if (shift > 4) return ReservedValue();
|
||||
|
||||
auto operand1 = Rn == Reg::SP ? SP(datasize) : X(datasize, Rn);
|
||||
auto operand2 = ExtendReg(datasize, Rm, option, shift);
|
||||
|
||||
auto result = ir.Add(operand1, operand2);
|
||||
|
||||
if (Rd == Reg::SP) {
|
||||
SP(datasize, result);
|
||||
} else {
|
||||
X(datasize, Rd, result);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::ADDS_ext(bool sf, Reg Rm, Imm<3> option, Imm<3> imm3, Reg Rn, Reg Rd) {
|
||||
size_t datasize = sf ? 64 : 32;
|
||||
u8 shift = imm3.ZeroExtend<u8>();
|
||||
if (shift > 4) return ReservedValue();
|
||||
|
||||
auto operand1 = Rn == Reg::SP ? SP(datasize) : X(datasize, Rn);
|
||||
auto operand2 = ExtendReg(datasize, Rm, option, shift);
|
||||
|
||||
auto result = ir.Add(operand1, operand2);
|
||||
|
||||
ir.SetNZCV(ir.NZCVFrom(result));
|
||||
|
||||
if (Rd == Reg::SP) {
|
||||
SP(datasize, result);
|
||||
} else {
|
||||
X(datasize, Rd, result);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::SUB_ext(bool sf, Reg Rm, Imm<3> option, Imm<3> imm3, Reg Rn, Reg Rd) {
|
||||
size_t datasize = sf ? 64 : 32;
|
||||
u8 shift = imm3.ZeroExtend<u8>();
|
||||
if (shift > 4) return ReservedValue();
|
||||
|
||||
auto operand1 = Rn == Reg::SP ? SP(datasize) : X(datasize, Rn);
|
||||
auto operand2 = ExtendReg(datasize, Rm, option, shift);
|
||||
|
||||
auto result = ir.Sub(operand1, operand2);
|
||||
|
||||
if (Rd == Reg::SP) {
|
||||
SP(datasize, result);
|
||||
} else {
|
||||
X(datasize, Rd, result);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::SUBS_ext(bool sf, Reg Rm, Imm<3> option, Imm<3> imm3, Reg Rn, Reg Rd) {
|
||||
size_t datasize = sf ? 64 : 32;
|
||||
u8 shift = imm3.ZeroExtend<u8>();
|
||||
if (shift > 4) return ReservedValue();
|
||||
|
||||
auto operand1 = Rn == Reg::SP ? SP(datasize) : X(datasize, Rn);
|
||||
auto operand2 = ExtendReg(datasize, Rm, option, shift);
|
||||
|
||||
auto result = ir.Sub(operand1, operand2);
|
||||
|
||||
ir.SetNZCV(ir.NZCVFrom(result));
|
||||
|
||||
if (Rd == Reg::SP) {
|
||||
SP(datasize, result);
|
||||
} else {
|
||||
X(datasize, Rd, result);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::ADC(bool sf, Reg Rm, Reg Rn, Reg Rd) {
|
||||
size_t datasize = sf ? 64 : 32;
|
||||
|
||||
auto operand1 = X(datasize, Rn);
|
||||
auto operand2 = X(datasize, Rm);
|
||||
|
||||
auto result = ir.AddWithCarry(operand1, operand2, ir.GetCFlag());
|
||||
|
||||
X(datasize, Rd, result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::ADCS(bool sf, Reg Rm, Reg Rn, Reg Rd) {
|
||||
size_t datasize = sf ? 64 : 32;
|
||||
|
||||
auto operand1 = X(datasize, Rn);
|
||||
auto operand2 = X(datasize, Rm);
|
||||
|
||||
auto result = ir.AddWithCarry(operand1, operand2, ir.GetCFlag());
|
||||
|
||||
ir.SetNZCV(ir.NZCVFrom(result));
|
||||
|
||||
X(datasize, Rd, result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::SBC(bool sf, Reg Rm, Reg Rn, Reg Rd) {
|
||||
size_t datasize = sf ? 64 : 32;
|
||||
|
||||
auto operand1 = X(datasize, Rn);
|
||||
auto operand2 = X(datasize, Rm);
|
||||
|
||||
auto result = ir.SubWithCarry(operand1, operand2, ir.GetCFlag());
|
||||
|
||||
X(datasize, Rd, result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TranslatorVisitor::SBCS(bool sf, Reg Rm, Reg Rn, Reg Rd) {
|
||||
size_t datasize = sf ? 64 : 32;
|
||||
|
||||
auto operand1 = X(datasize, Rn);
|
||||
auto operand2 = X(datasize, Rm);
|
||||
|
||||
auto result = ir.SubWithCarry(operand1, operand2, ir.GetCFlag());
|
||||
|
||||
ir.SetNZCV(ir.NZCVFrom(result));
|
||||
|
||||
X(datasize, Rd, result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace A64
|
||||
} // namespace Dynarmic
|
||||
|
||||
@@ -25,6 +25,18 @@ bool TranslatorVisitor::ReservedValue() {
|
||||
return false;
|
||||
}
|
||||
|
||||
IR::U32U64 TranslatorVisitor::I(size_t bitsize, u64 value) {
|
||||
switch (bitsize) {
|
||||
case 32:
|
||||
return ir.Imm32(static_cast<u32>(value));
|
||||
case 64:
|
||||
return ir.Imm64(value);
|
||||
default:
|
||||
ASSERT_MSG(false, "Imm - get: Invalid bitsize");
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
IR::U32U64 TranslatorVisitor::X(size_t bitsize, Reg reg) {
|
||||
switch (bitsize) {
|
||||
case 32:
|
||||
@@ -50,6 +62,31 @@ void TranslatorVisitor::X(size_t bitsize, Reg reg, IR::U32U64 value) {
|
||||
}
|
||||
}
|
||||
|
||||
IR::U32U64 TranslatorVisitor::SP(size_t bitsize) {
|
||||
switch (bitsize) {
|
||||
case 32:
|
||||
return ir.LeastSignificantWord(ir.GetSP());
|
||||
case 64:
|
||||
return ir.GetSP();
|
||||
default:
|
||||
ASSERT_MSG(false, "SP - get : Invalid bitsize");
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
void TranslatorVisitor::SP(size_t bitsize, IR::U32U64 value) {
|
||||
switch (bitsize) {
|
||||
case 32:
|
||||
ir.SetSP(ir.ZeroExtendWordToLong(value));
|
||||
break;
|
||||
case 64:
|
||||
ir.SetSP(value);
|
||||
break;
|
||||
default:
|
||||
ASSERT_MSG(false, "SP - : Invalid bitsize");
|
||||
}
|
||||
}
|
||||
|
||||
IR::U32U64 TranslatorVisitor::ShiftReg(size_t bitsize, Reg reg, Imm<2> shift, IR::U8 amount) {
|
||||
auto result = X(bitsize, reg);
|
||||
switch (shift.ZeroExtend()) {
|
||||
@@ -66,5 +103,81 @@ IR::U32U64 TranslatorVisitor::ShiftReg(size_t bitsize, Reg reg, Imm<2> shift, IR
|
||||
return {};
|
||||
}
|
||||
|
||||
IR::U32U64 TranslatorVisitor::ExtendReg(size_t bitsize, Reg reg, Imm<3> option, u8 shift) {
|
||||
ASSERT(shift <= 4);
|
||||
ASSERT(bitsize == 32 || bitsize == 64);
|
||||
IR::UAny val = X(bitsize, reg);
|
||||
size_t len;
|
||||
IR::U32U64 extended;
|
||||
bool signed_extend;
|
||||
|
||||
switch (option.ZeroExtend()) {
|
||||
case 0b000: { // UXTB
|
||||
val = ir.LeastSignificantByte(val);
|
||||
len = 8;
|
||||
signed_extend = false;
|
||||
break;
|
||||
}
|
||||
case 0b001: { // UXTH
|
||||
val = ir.LeastSignificantHalf(val);
|
||||
len = 16;
|
||||
signed_extend = false;
|
||||
break;
|
||||
}
|
||||
case 0b010: { // UXTW
|
||||
if (bitsize != 32) {
|
||||
val = ir.LeastSignificantWord(val);
|
||||
}
|
||||
len = 32;
|
||||
signed_extend = false;
|
||||
break;
|
||||
}
|
||||
case 0b011: { // UXTX
|
||||
len = 64;
|
||||
signed_extend = false;
|
||||
break;
|
||||
}
|
||||
case 0b100: { // SXTB
|
||||
val = ir.LeastSignificantByte(val);
|
||||
len = 8;
|
||||
signed_extend = true;
|
||||
break;
|
||||
}
|
||||
case 0b101: { // SXTH
|
||||
val = ir.LeastSignificantHalf(val);
|
||||
len = 16;
|
||||
signed_extend = true;
|
||||
break;
|
||||
}
|
||||
case 0b110: { // SXTW
|
||||
if (bitsize != 32) {
|
||||
val = ir.LeastSignificantWord(val);
|
||||
}
|
||||
len = 32;
|
||||
signed_extend = true;
|
||||
break;
|
||||
}
|
||||
case 0b111: { // SXTX
|
||||
len = 64;
|
||||
signed_extend = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ASSERT_MSG(false, "Unreachable");
|
||||
}
|
||||
|
||||
if (len < bitsize) {
|
||||
if (bitsize == 32) {
|
||||
extended = signed_extend ? ir.SignExtendToWord(val) : ir.ZeroExtendToWord(val);
|
||||
} else {
|
||||
extended = signed_extend ? ir.SignExtendToLong(val) : ir.ZeroExtendToLong(val);
|
||||
}
|
||||
} else {
|
||||
extended = val;
|
||||
}
|
||||
|
||||
return ir.LogicalShiftLeft(extended, ir.Imm8(shift));
|
||||
}
|
||||
|
||||
} // namespace A64
|
||||
} // namespace Dynarmic
|
||||
|
||||
@@ -25,10 +25,14 @@ struct TranslatorVisitor final {
|
||||
bool UnpredictableInstruction();
|
||||
bool ReservedValue();
|
||||
|
||||
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);
|
||||
IR::U32U64 SP(size_t bitsize);
|
||||
void SP(size_t bitsize, IR::U32U64 value);
|
||||
|
||||
IR::U32U64 ShiftReg(size_t bitsize, Reg reg, Imm<2> shift, IR::U8 amount);
|
||||
IR::U32U64 ExtendReg(size_t bitsize, Reg reg, Imm<3> option, u8 shift);
|
||||
|
||||
// Data processing - Immediate - PC relative addressing
|
||||
bool ADR(Imm<2> immlo, Imm<19> immhi, Reg Rd);
|
||||
|
||||
Reference in New Issue
Block a user