A64: Implement compare and branch

This commit is contained in:
MerryMage
2018-01-07 16:33:02 +00:00
parent e8bcf72ee5
commit cb481a3a48
20 changed files with 249 additions and 21 deletions

View File

@@ -1161,6 +1161,10 @@ 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::CheckHalt terminal, IR::LocationDescriptor initial_location) {
code->cmp(code->byte[r15 + offsetof(A32JitState, halt_requested)], u8(0));
code->jne(code->GetForceReturnFromRunCodeAddress());

View File

@@ -77,6 +77,7 @@ protected:
void EmitTerminalImpl(IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location) override;
void EmitTerminalImpl(IR::Term::PopRSBHint terminal, IR::LocationDescriptor initial_location) override;
void EmitTerminalImpl(IR::Term::If terminal, IR::LocationDescriptor initial_location) override;
void EmitTerminalImpl(IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location) override;
void EmitTerminalImpl(IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location) override;
// Patching

View File

@@ -115,6 +115,12 @@ A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) {
return block_desc;
}
void A64EmitX64::EmitA64SetCheckBit(A64EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg8 to_store = ctx.reg_alloc.UseGpr(args[0]).cvt8();
code->mov(code->byte[r15 + offsetof(A64JitState, check_bit)], to_store);
}
void A64EmitX64::EmitA64GetCFlag(A64EmitContext& ctx, IR::Inst* inst) {
Xbyak::Reg32 result = ctx.reg_alloc.ScratchGpr().cvt32();
code->mov(result, dword[r15 + offsetof(A64JitState, CPSR_nzcv)]);
@@ -267,6 +273,15 @@ void A64EmitX64::EmitTerminalImpl(IR::Term::If terminal, IR::LocationDescriptor
EmitTerminal(terminal.then_, initial_location);
}
void A64EmitX64::EmitTerminalImpl(IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location) {
Xbyak::Label fail;
code->cmp(code->byte[r15 + offsetof(A64JitState, check_bit)], u8(0));
code->jz(fail);
EmitTerminal(terminal.then_, initial_location);
code->L(fail);
EmitTerminal(terminal.else_, initial_location);
}
void A64EmitX64::EmitTerminalImpl(IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location) {
code->cmp(code->byte[r15 + offsetof(A64JitState, halt_requested)], u8(0));
code->jne(code->GetForceReturnFromRunCodeAddress());

View File

@@ -66,6 +66,7 @@ protected:
void EmitTerminalImpl(IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location) override;
void EmitTerminalImpl(IR::Term::PopRSBHint terminal, IR::LocationDescriptor initial_location) override;
void EmitTerminalImpl(IR::Term::If terminal, IR::LocationDescriptor initial_location) override;
void EmitTerminalImpl(IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location) override;
void EmitTerminalImpl(IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location) override;
// Patching

View File

@@ -55,6 +55,7 @@ struct A64JitState {
s64 cycles_to_run = 0;
s64 cycles_remaining = 0;
bool halt_requested = false;
bool check_bit = false;
static constexpr size_t RSBSize = 8; // MUST be a power of 2.
static constexpr size_t RSBPtrMask = RSBSize - 1;

View File

@@ -218,7 +218,7 @@ void EmitX64<JST>::EmitMostSignificantBit(EmitContext& ctx, IR::Inst* inst) {
}
template <typename JST>
void EmitX64<JST>::EmitIsZero(EmitContext& ctx, IR::Inst* inst) {
void EmitX64<JST>::EmitIsZero32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(args[0]).cvt32();
// TODO: Flag optimization
@@ -239,6 +239,17 @@ void EmitX64<JST>::EmitIsZero64(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result);
}
template <typename JST>
void EmitX64<JST>::EmitTestBit(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
ASSERT(args[1].IsImmediate());
// TODO: Flag optimization
code->bt(result, args[1].GetImmediateU8());
code->setc(result.cvt8());
ctx.reg_alloc.DefineValue(inst, result);
}
template <typename JST>
void EmitX64<JST>::EmitLogicalShiftLeft32(EmitContext& ctx, IR::Inst* inst) {
auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);

View File

@@ -92,6 +92,7 @@ protected:
virtual void EmitTerminalImpl(IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location) = 0;
virtual void EmitTerminalImpl(IR::Term::PopRSBHint terminal, IR::LocationDescriptor initial_location) = 0;
virtual void EmitTerminalImpl(IR::Term::If terminal, IR::LocationDescriptor initial_location) = 0;
virtual void EmitTerminalImpl(IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location) = 0;
virtual void EmitTerminalImpl(IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location) = 0;
// Patching