Implement Thumb PUSH instruction

This commit is contained in:
MerryMage 2016-07-18 15:11:16 +01:00
parent 9109b226af
commit f7e3d7b8d2
10 changed files with 191 additions and 54 deletions

View file

@ -124,7 +124,7 @@ boost::optional<const Thumb16Matcher<V>&> DecodeThumb16(u16 instruction) {
INST(&V::thumb16_SXTB, "SXTB", "1011001001mmmddd"), // v6
INST(&V::thumb16_UXTH, "UXTH", "1011001010mmmddd"), // v6
INST(&V::thumb16_UXTB, "UXTB", "1011001011mmmddd"), // v6
//INST(&V::thumb16_PUSH, "PUSH", "1011010rxxxxxxxx"), // v4T
INST(&V::thumb16_PUSH, "PUSH", "1011010Mxxxxxxxx"), // v4T
//INST(&V::thumb16_POP, "POP", "1011110rxxxxxxxx"), // v4T
//INST(&V::thumb16_SETEND, "SETEND", "101101100101x000"), // v6
//INST(&V::thumb16_CPS, "CPS", "10110110011m0aif"), // v6

View file

@ -280,6 +280,24 @@ public:
return Common::StringFromFormat("uxtb %s, %s", RegStr(d), RegStr(m));
}
std::string thumb16_PUSH(bool M, RegList reg_list) {
if (M)
reg_list |= 1 << 14;
std::string ret = "PUSH ";
bool first_reg = true;
for (size_t i = 0; i < 16; i++) {
if (Common::Bit(i, reg_list)) {
if (!first_reg)
ret += ", ";
ret += RegStr(static_cast<Reg>(i));
first_reg = false;
}
}
return ret;
}
std::string thumb16_REV(Reg m, Reg d) {
return Common::StringFromFormat("rev %s, %s", RegStr(d), RegStr(m));
}

View file

@ -155,6 +155,10 @@ IREmitter::ResultAndCarryAndOverflow IREmitter::SubWithCarry(IR::ValuePtr a, IR:
return {result, carry_out, overflow};
}
IR::ValuePtr IREmitter::Sub(IR::ValuePtr a, IR::ValuePtr b) {
return Inst(IR::Opcode::SubWithCarry, {a, b, Imm1(1)});
}
IR::ValuePtr IREmitter::And(IR::ValuePtr a, IR::ValuePtr b) {
return Inst(IR::Opcode::And, {a, b});
}

View file

@ -64,6 +64,7 @@ public:
ResultAndCarryAndOverflow AddWithCarry(IR::ValuePtr a, IR::ValuePtr b, IR::ValuePtr carry_in);
IR::ValuePtr Add(IR::ValuePtr a, IR::ValuePtr b);
ResultAndCarryAndOverflow SubWithCarry(IR::ValuePtr a, IR::ValuePtr b, IR::ValuePtr carry_in);
IR::ValuePtr Sub(IR::ValuePtr a, IR::ValuePtr b);
IR::ValuePtr And(IR::ValuePtr a, IR::ValuePtr b);
IR::ValuePtr Eor(IR::ValuePtr a, IR::ValuePtr b);
IR::ValuePtr Or(IR::ValuePtr a, IR::ValuePtr b);

View file

@ -7,6 +7,7 @@
#include <tuple>
#include "common/assert.h"
#include "common/bit_util.h"
#include "frontend/arm_types.h"
#include "frontend/decoder/thumb16.h"
#include "frontend/ir/ir_emitter.h"
@ -507,6 +508,28 @@ struct ThumbTranslatorVisitor final {
return true;
}
bool thumb16_PUSH(bool M, RegList reg_list) {
if (M) reg_list |= 1 << 14;
if (Common::BitCount(reg_list) < 1) {
return UnpredictableInstruction();
}
// PUSH <reg_list>
// reg_list cannot encode for R15.
u32 num_bytes_to_push = static_cast<u32>(4 * Common::BitCount(reg_list));
const auto final_address = ir.Sub(ir.GetRegister(Reg::SP), ir.Imm32(num_bytes_to_push));
auto address = final_address;
for (size_t i = 0; i < 16; i++) {
if (Common::Bit(i, reg_list)) {
auto Ri = ir.GetRegister(static_cast<Reg>(i));
ir.WriteMemory32(address, Ri);
address = ir.Add(address, ir.Imm32(4));
}
}
ir.SetRegister(Reg::SP, final_address);
// TODO(optimization): Possible location for an RSB push.
return true;
}
bool thumb16_REV(Reg m, Reg d) {
// REV <Rd>, <Rm>
// Rd cannot encode R15.