frontend/ir/ir_emitter: Add A32 equivalent to A64's SetCheckBit
This will be used in a subsequent change to implement ARMv6T2's CBZ/CBNZ Thumb-1 instructions.
This commit is contained in:
parent
1c47e638fc
commit
bd755ae494
7 changed files with 29 additions and 3 deletions
|
@ -501,6 +501,12 @@ void A32EmitX64::EmitA32SetZFlag(A32EmitContext& ctx, IR::Inst* inst) {
|
|||
}
|
||||
}
|
||||
|
||||
void A32EmitX64::EmitA32SetCheckBit(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
const Xbyak::Reg8 to_store = ctx.reg_alloc.UseGpr(args[0]).cvt8();
|
||||
code.mov(code.byte[r15 + offsetof(A32JitState, check_bit)], to_store);
|
||||
}
|
||||
|
||||
void A32EmitX64::EmitA32GetCFlag(A32EmitContext& ctx, IR::Inst* inst) {
|
||||
const Xbyak::Reg32 result = ctx.reg_alloc.ScratchGpr().cvt32();
|
||||
code.mov(result, dword[r15 + offsetof(A32JitState, CPSR_nzcv)]);
|
||||
|
@ -1320,8 +1326,13 @@ void A32EmitX64::EmitTerminalImpl(IR::Term::If terminal, IR::LocationDescriptor
|
|||
EmitTerminal(terminal.then_, initial_location);
|
||||
}
|
||||
|
||||
void A32EmitX64::EmitTerminalImpl(IR::Term::CheckBit, IR::LocationDescriptor) {
|
||||
ASSERT_MSG(false, "Term::CheckBit should never be emitted by the A32 frontend");
|
||||
void A32EmitX64::EmitTerminalImpl(IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location) {
|
||||
Xbyak::Label fail;
|
||||
code.cmp(code.byte[r15 + offsetof(A32JitState, check_bit)], u8(0));
|
||||
code.jz(fail);
|
||||
EmitTerminal(terminal.then_, initial_location);
|
||||
code.L(fail);
|
||||
EmitTerminal(terminal.else_, initial_location);
|
||||
}
|
||||
|
||||
void A32EmitX64::EmitTerminalImpl(IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location) {
|
||||
|
|
|
@ -53,6 +53,7 @@ struct A32JitState {
|
|||
s64 cycles_to_run = 0;
|
||||
s64 cycles_remaining = 0;
|
||||
bool halt_requested = false;
|
||||
bool check_bit = false;
|
||||
|
||||
// Exclusive state
|
||||
static constexpr u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8;
|
||||
|
|
|
@ -106,6 +106,10 @@ void IREmitter::SetCpsrNZCVQ(const IR::U32& value) {
|
|||
Inst(Opcode::A32SetCpsrNZCVQ, value);
|
||||
}
|
||||
|
||||
void IREmitter::SetCheckBit(const IR::U1& value) {
|
||||
Inst(Opcode::A32SetCheckBit, value);
|
||||
}
|
||||
|
||||
IR::U1 IREmitter::GetCFlag() {
|
||||
return Inst<IR::U1>(Opcode::A32GetCFlag);
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ public:
|
|||
void SetCpsr(const IR::U32& value);
|
||||
void SetCpsrNZCV(const IR::U32& value);
|
||||
void SetCpsrNZCVQ(const IR::U32& value);
|
||||
void SetCheckBit(const IR::U1& value);
|
||||
IR::U1 GetCFlag();
|
||||
void SetNFlag(const IR::U1& value);
|
||||
void SetZFlag(const IR::U1& value);
|
||||
|
|
|
@ -477,10 +477,15 @@ bool Inst::IsCoprocessorInstruction() const {
|
|||
}
|
||||
}
|
||||
|
||||
bool Inst::IsSetCheckBitOperation() const {
|
||||
return op == Opcode::A32SetCheckBit ||
|
||||
op == Opcode::A64SetCheckBit;
|
||||
}
|
||||
|
||||
bool Inst::MayHaveSideEffects() const {
|
||||
return op == Opcode::PushRSB ||
|
||||
op == Opcode::A64SetCheckBit ||
|
||||
op == Opcode::A64DataCacheOperationRaised ||
|
||||
IsSetCheckBitOperation() ||
|
||||
IsBarrier() ||
|
||||
CausesCPUException() ||
|
||||
WritesToCoreRegister() ||
|
||||
|
|
|
@ -99,6 +99,9 @@ public:
|
|||
/// Determines whether or not this instruction causes a CPU exception.
|
||||
bool CausesCPUException() const;
|
||||
|
||||
/// Determines whether or not this instruction is a SetCheckBit operation.
|
||||
bool IsSetCheckBitOperation() const;
|
||||
|
||||
/// Determines whether or not this instruction may have side-effects.
|
||||
bool MayHaveSideEffects() const;
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ OPCODE(Identity, Opaque, Opaq
|
|||
OPCODE(Breakpoint, Void, )
|
||||
|
||||
// A32 Context getters/setters
|
||||
A32OPC(SetCheckBit, Void, U1 )
|
||||
A32OPC(GetRegister, U32, A32Reg )
|
||||
A32OPC(GetExtendedRegister32, U32, A32ExtReg )
|
||||
A32OPC(GetExtendedRegister64, U64, A32ExtReg )
|
||||
|
|
Loading…
Reference in a new issue