VFP: Implement {Get,Set}ExtendedRegister{32,64}

This commit is contained in:
MerryMage 2016-08-05 18:54:19 +01:00
parent d31bbd6d14
commit 640ce48baa
15 changed files with 262 additions and 16 deletions

View file

@ -51,6 +51,17 @@ inline const char* RegToString(Reg reg) {
return reg_strs.at(static_cast<size_t>(reg));
}
enum class ExtReg {
S0, S1, S2, S3, S4, S5, S6, S7,
S8, S9, S10, S11, S12, S13, S14, S15,
S16, S17, S18, S19, S20, S21, S22, S23,
S24, S25, S26, S27, S28, S29, S30, S31,
D0, D1, D2, D3, D4, D5, D6, D7,
D8, D9, D10, D11, D12, D13, D14, D15,
D16, D17, D18, D19, D20, D21, D22, D23,
D24, D25, D26, D27, D28, D29, D30, D31,
};
using Imm3 = u32;
using Imm4 = u32;
using Imm5 = u32;

View file

@ -78,6 +78,11 @@ Arm::Reg Value::GetRegRef() const {
return inner.imm_regref;
}
Arm::ExtReg Value::GetExtRegRef() const {
DEBUG_ASSERT(type == Type::ExtRegRef);
return inner.imm_extregref;
}
Inst* Value::GetInst() const {
DEBUG_ASSERT(type == Type::Opaque);
return inner.inst;

View file

@ -33,16 +33,17 @@ namespace IR {
// A basic block is represented as an IR::Block.
enum class Type {
Void = 1 << 0,
RegRef = 1 << 1,
Opaque = 1 << 2,
U1 = 1 << 3,
U8 = 1 << 4,
U16 = 1 << 5,
U32 = 1 << 6,
U64 = 1 << 7,
F32 = 1 << 8,
F64 = 1 << 9,
Void = 1 << 0,
RegRef = 1 << 1,
ExtRegRef = 1 << 2,
Opaque = 1 << 3,
U1 = 1 << 4,
U8 = 1 << 5,
U16 = 1 << 6,
U32 = 1 << 7,
U64 = 1 << 8,
F32 = 1 << 9,
F64 = 1 << 10,
};
Type GetTypeOf(Opcode op);
@ -72,6 +73,10 @@ public:
inner.imm_regref = value;
}
explicit Value(Arm::ExtReg value) : type(Type::ExtRegRef) {
inner.imm_extregref = value;
}
explicit Value(bool value) : type(Type::U1) {
inner.imm_u1 = value;
}
@ -90,6 +95,7 @@ public:
Inst* GetInst() const;
Arm::Reg GetRegRef() const;
Arm::ExtReg GetExtRegRef() const;
bool GetU1() const;
u8 GetU8() const;
u32 GetU32() const;
@ -100,6 +106,7 @@ private:
union {
Inst* inst; // type == Type::Opaque
Arm::Reg imm_regref;
Arm::ExtReg imm_extregref;
bool imm_u1;
u8 imm_u8;
u32 imm_u32;

View file

@ -43,11 +43,31 @@ IR::Value IREmitter::GetRegister(Reg reg) {
return Inst(IR::Opcode::GetRegister, { IR::Value(reg) });
}
IR::Value IREmitter::GetExtendedRegister(ExtReg reg) {
if (reg >= Arm::ExtReg::S0 && reg <= Arm::ExtReg::S31) {
return Inst(IR::Opcode::GetExtendedRegister32, {IR::Value(reg)});
} else if (reg >= Arm::ExtReg::D0 && reg <= Arm::ExtReg::D31) {
return Inst(IR::Opcode::GetExtendedRegister64, {IR::Value(reg)});
} else {
ASSERT_MSG(false, "Invalid reg.");
}
}
void IREmitter::SetRegister(const Reg reg, const IR::Value& value) {
ASSERT(reg != Reg::PC);
Inst(IR::Opcode::SetRegister, { IR::Value(reg), value });
}
void IREmitter::SetExtendedRegister(const ExtReg reg, const IR::Value& value) {
if (reg >= Arm::ExtReg::S0 && reg <= Arm::ExtReg::S31) {
Inst(IR::Opcode::SetExtendedRegister32, {IR::Value(reg), value});
} else if (reg >= Arm::ExtReg::D0 && reg <= Arm::ExtReg::D31) {
Inst(IR::Opcode::SetExtendedRegister64, {IR::Value(reg), value});
} else {
ASSERT_MSG(false, "Invalid reg.");
}
}
void IREmitter::ALUWritePC(const IR::Value& value) {
// This behaviour is ARM version-dependent.
// The below implementation is for ARMv6k

View file

@ -40,7 +40,9 @@ public:
IR::Value Imm32(u32 value);
IR::Value GetRegister(Reg source_reg);
IR::Value GetExtendedRegister(ExtReg source_reg);
void SetRegister(const Reg dest_reg, const IR::Value& value);
void SetExtendedRegister(const ExtReg dest_reg, const IR::Value& value);
void ALUWritePC(const IR::Value& value);
void BranchWritePC(const IR::Value& value);

View file

@ -5,7 +5,11 @@ OPCODE(Breakpoint, T::Void,
// ARM Context getters/setters
OPCODE(GetRegister, T::U32, T::RegRef )
OPCODE(GetExtendedRegister32, T::F32, T::ExtRegRef )
OPCODE(GetExtendedRegister64, T::F64, T::ExtRegRef )
OPCODE(SetRegister, T::Void, T::RegRef, T::U32 )
OPCODE(SetExtendedRegister32, T::Void, T::ExtRegRef, T::F32 )
OPCODE(SetExtendedRegister64, T::Void, T::ExtRegRef, T::F64 )
OPCODE(GetNFlag, T::U1, )
OPCODE(SetNFlag, T::Void, T::U1 )
OPCODE(GetZFlag, T::U1, )