Adding bl (unconditional only).
This commit is contained in:
@@ -63,117 +63,124 @@ namespace x64 {
|
||||
// return e.GenerateIndirectionBranch(cia, target, lk, likely_local);
|
||||
// }
|
||||
|
||||
// int XeEmitBranchTo(
|
||||
// X64Emitter& e, X86Compiler& c, const char* src, uint32_t cia,
|
||||
// bool lk, jit_value_t condition) {
|
||||
// FunctionBlock* fn_block = e.fn_block();
|
||||
int XeEmitBranchTo(
|
||||
X64Emitter& e, X86Compiler& c, const char* src, uint32_t cia,
|
||||
bool lk, void* condition = NULL) {
|
||||
FunctionBlock* fn_block = e.fn_block();
|
||||
|
||||
// // Fast-path for branches to other blocks.
|
||||
// // Only valid when not tracing branches.
|
||||
// if (!FLAGS_trace_branches &&
|
||||
// fn_block->outgoing_type == FunctionBlock::kTargetBlock) {
|
||||
// e.branch_to_block_if(fn_block->outgoing_address, condition);
|
||||
// return 0;
|
||||
// }
|
||||
// Fast-path for branches to other blocks.
|
||||
// Only valid when not tracing branches.
|
||||
if (fn_block->outgoing_type == FunctionBlock::kTargetBlock) {
|
||||
if (condition) {
|
||||
XEASSERTALWAYS();
|
||||
} else {
|
||||
//e.TraceBranch(cia);
|
||||
//c.jmp(e.GetBlockLabel(fn_block->outgoing_address));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// // Only branch of conditionals when we have one.
|
||||
// jit_label_t post_jump_label = jit_label_undefined;
|
||||
// if (condition) {
|
||||
// // TODO(benvanik): add debug info for this?
|
||||
// // char name[32];
|
||||
// // xesnprintfa(name, XECOUNT(name), "loc_%.8X_bcx", i.address);
|
||||
// jit_insn_branch_if_not(f, condition, &post_jump_label);
|
||||
// }
|
||||
// Only branch of conditionals when we have one.
|
||||
//jit_label_t post_jump_label = jit_label_undefined;
|
||||
if (condition) {
|
||||
// TODO(benvanik): add debug info for this?
|
||||
// char name[32];
|
||||
// xesnprintfa(name, XECOUNT(name), "loc_%.8X_bcx", i.address);
|
||||
//jit_insn_branch_if_not(f, condition, &post_jump_label);
|
||||
XEASSERTALWAYS();
|
||||
}
|
||||
|
||||
// if (FLAGS_trace_branches) {
|
||||
// e.TraceBranch(cia);
|
||||
// }
|
||||
e.TraceBranch(cia);
|
||||
|
||||
// // Get the basic block and switch behavior based on outgoing type.
|
||||
// int result = 0;
|
||||
// switch (fn_block->outgoing_type) {
|
||||
// case FunctionBlock::kTargetBlock:
|
||||
// // Taken care of above usually.
|
||||
// e.branch_to_block(fn_block->outgoing_address);
|
||||
// break;
|
||||
// case FunctionBlock::kTargetFunction:
|
||||
// {
|
||||
// // Spill all registers to memory.
|
||||
// // TODO(benvanik): only spill ones used by the target function? Use
|
||||
// // calling convention flags on the function to not spill temp
|
||||
// // registers?
|
||||
// e.SpillRegisters();
|
||||
// Get the basic block and switch behavior based on outgoing type.
|
||||
int result = 0;
|
||||
switch (fn_block->outgoing_type) {
|
||||
case FunctionBlock::kTargetBlock:
|
||||
// Taken care of above.
|
||||
XEASSERTALWAYS();
|
||||
result = 1;
|
||||
break;
|
||||
case FunctionBlock::kTargetFunction:
|
||||
{
|
||||
// Spill all registers to memory.
|
||||
// TODO(benvanik): only spill ones used by the target function? Use
|
||||
// calling convention flags on the function to not spill temp
|
||||
// registers?
|
||||
e.SpillRegisters();
|
||||
|
||||
// XEASSERTNOTNULL(fn_block->outgoing_function);
|
||||
// // TODO(benvanik): check to see if this is the last block in the function.
|
||||
// // This would enable tail calls/etc.
|
||||
// bool is_end = false;
|
||||
// if (!lk || is_end) {
|
||||
// // Tail. No need to refill the local register values, just return.
|
||||
// // We optimize this by passing in the LR from our parent instead of the
|
||||
// // next instruction. This allows the return from our callee to pop
|
||||
// // all the way up.
|
||||
// e.call_function(fn_block->outgoing_function,
|
||||
// jit_value_get_param(f, 1), true);
|
||||
// jit_insn_return(f, NULL);
|
||||
// } else {
|
||||
// // Will return here eventually.
|
||||
// // Refill registers from state.
|
||||
// e.call_function(fn_block->outgoing_function,
|
||||
// e.get_uint64(cia + 4), false);
|
||||
// e.FillRegisters();
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// case FunctionBlock::kTargetLR:
|
||||
// {
|
||||
// // An indirect jump.
|
||||
// printf("INDIRECT JUMP VIA LR: %.8X\n", cia);
|
||||
// result = XeEmitIndirectBranchTo(e, f, src, cia, lk, kXEPPCRegLR);
|
||||
// break;
|
||||
// }
|
||||
// case FunctionBlock::kTargetCTR:
|
||||
// {
|
||||
// // An indirect jump.
|
||||
// printf("INDIRECT JUMP VIA CTR: %.8X\n", cia);
|
||||
// result = XeEmitIndirectBranchTo(e, f, src, cia, lk, kXEPPCRegCTR);
|
||||
// break;
|
||||
// }
|
||||
// default:
|
||||
// case FunctionBlock::kTargetNone:
|
||||
// XEASSERTALWAYS();
|
||||
// result = 1;
|
||||
// break;
|
||||
// }
|
||||
XEASSERTNOTNULL(fn_block->outgoing_function);
|
||||
// TODO(benvanik): check to see if this is the last block in the function.
|
||||
// This would enable tail calls/etc.
|
||||
bool is_end = false;
|
||||
if (!lk || is_end) {
|
||||
// Tail. No need to refill the local register values, just return.
|
||||
// We optimize this by passing in the LR from our parent instead of the
|
||||
// next instruction. This allows the return from our callee to pop
|
||||
// all the way up.
|
||||
e.CallFunction(fn_block->outgoing_function, c.getGpArg(1), true);
|
||||
// No ret needed - we jumped!
|
||||
} else {
|
||||
// Will return here eventually.
|
||||
// Refill registers from state.
|
||||
GpVar lr(c.newGpVar());
|
||||
c.mov(lr, imm(cia + 4));
|
||||
e.CallFunction(fn_block->outgoing_function, lr, false);
|
||||
e.FillRegisters();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FunctionBlock::kTargetLR:
|
||||
{
|
||||
// An indirect jump.
|
||||
printf("INDIRECT JUMP VIA LR: %.8X\n", cia);
|
||||
XEASSERTALWAYS();
|
||||
//result = XeEmitIndirectBranchTo(e, c, src, cia, lk, kXEPPCRegLR);
|
||||
break;
|
||||
}
|
||||
case FunctionBlock::kTargetCTR:
|
||||
{
|
||||
// An indirect jump.
|
||||
printf("INDIRECT JUMP VIA CTR: %.8X\n", cia);
|
||||
XEASSERTALWAYS();
|
||||
//result = XeEmitIndirectBranchTo(e, c, src, cia, lk, kXEPPCRegCTR);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
case FunctionBlock::kTargetNone:
|
||||
XEASSERTALWAYS();
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// if (condition) {
|
||||
// jit_insn_label(f, &post_jump_label);
|
||||
// }
|
||||
if (condition) {
|
||||
XEASSERTALWAYS();
|
||||
//jit_insn_label(f, &post_jump_label);
|
||||
}
|
||||
|
||||
// return result;
|
||||
// }
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// XEEMITTER(bx, 0x48000000, I )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
// // if AA then
|
||||
// // NIA <- EXTS(LI || 0b00)
|
||||
// // else
|
||||
// // NIA <- CIA + EXTS(LI || 0b00)
|
||||
// // if LK then
|
||||
// // LR <- CIA + 4
|
||||
XEEMITTER(bx, 0x48000000, I )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
// if AA then
|
||||
// NIA <- EXTS(LI || 0b00)
|
||||
// else
|
||||
// NIA <- CIA + EXTS(LI || 0b00)
|
||||
// if LK then
|
||||
// LR <- CIA + 4
|
||||
|
||||
// uint32_t nia;
|
||||
// if (i.I.AA) {
|
||||
// nia = XEEXTS26(i.I.LI << 2);
|
||||
// } else {
|
||||
// nia = i.address + XEEXTS26(i.I.LI << 2);
|
||||
// }
|
||||
// if (i.I.LK) {
|
||||
// e.update_lr_value(e.get_uint64(i.address + 4));
|
||||
// }
|
||||
uint32_t nia;
|
||||
if (i.I.AA) {
|
||||
nia = XEEXTS26(i.I.LI << 2);
|
||||
} else {
|
||||
nia = i.address + XEEXTS26(i.I.LI << 2);
|
||||
}
|
||||
if (i.I.LK) {
|
||||
e.update_lr_value(imm(i.address + 4));
|
||||
}
|
||||
|
||||
// return XeEmitBranchTo(e, f, "bx", i.address, i.I.LK, NULL);
|
||||
// }
|
||||
return XeEmitBranchTo(e, c, "bx", i.address, i.I.LK);
|
||||
}
|
||||
|
||||
// XEEMITTER(bcx, 0x40000000, B )(X64Emitter& e, X86Compiler& c, InstrData& i) {
|
||||
// // if ¬BO[2] then
|
||||
@@ -244,7 +251,7 @@ namespace x64 {
|
||||
// } else {
|
||||
// nia = i.address + XEEXTS26(i.B.BD << 2);
|
||||
// }
|
||||
// if (XeEmitBranchTo(e, f, "bcx", i.address, i.B.LK, ok)) {
|
||||
// if (XeEmitBranchTo(e, c, "bcx", i.address, i.B.LK, ok)) {
|
||||
// return 1;
|
||||
// }
|
||||
|
||||
@@ -287,7 +294,7 @@ namespace x64 {
|
||||
// ok = cond_ok;
|
||||
// }
|
||||
|
||||
// if (XeEmitBranchTo(e, f, "bcctrx", i.address, i.XL.LK, ok)) {
|
||||
// if (XeEmitBranchTo(e, c, "bcctrx", i.address, i.XL.LK, ok)) {
|
||||
// return 1;
|
||||
// }
|
||||
|
||||
@@ -353,7 +360,7 @@ namespace x64 {
|
||||
// ok = cond_ok;
|
||||
// }
|
||||
|
||||
// if (XeEmitBranchTo(e, f, "bclrx", i.address, i.XL.LK, ok)) {
|
||||
// if (XeEmitBranchTo(e, c, "bclrx", i.address, i.XL.LK, ok)) {
|
||||
// return 1;
|
||||
// }
|
||||
|
||||
@@ -657,7 +664,7 @@ XEEMITTER(mtspr, 0x7C0003A6, XFX)(X64Emitter& e, X86Compiler& c, InstrDat
|
||||
|
||||
|
||||
void X64RegisterEmitCategoryControl() {
|
||||
// XEREGISTERINSTR(bx, 0x48000000);
|
||||
XEREGISTERINSTR(bx, 0x48000000);
|
||||
// XEREGISTERINSTR(bcx, 0x40000000);
|
||||
// XEREGISTERINSTR(bcctrx, 0x4C000420);
|
||||
// XEREGISTERINSTR(bclrx, 0x4C000020);
|
||||
|
||||
Reference in New Issue
Block a user