in src/disasm.cpp [1952:2052]
bool DETOUR_IA64_BUNDLE::RelocateInstruction(_Inout_ DETOUR_IA64_BUNDLE* pDst,
_In_ BYTE slot,
_Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const
/*
If pBundleExtra is provided and instruction is IP-relative,
this function relocates instruction to target pBundleExtra,
pBundleExtra is set to brl the original target, and return true.
[Not used] If pBundleExtra is not provided and instruction is IP-relative, return true.
Else return false.
The following IP-relative forms are recognized:
br and br.call
chk.s.m integer and float
chk.a.nc integer and float
chk.a.clr integer and float
chk.s.i
fchkf
Brl is handled elsewhere, because the code was previously written.
Branch prediction hints are not relocated.
*/
{
UINT64 const instruction = GetInstruction(slot);
UINT64 const opcode = GetOpcode(instruction);
size_t const dest = (size_t)pDst;
size_t const extra = (size_t)pBundleExtra;
switch (GetUnit(slot)) {
case F_UNIT:
// F14 fchkf
if (opcode == 0 && GetX(instruction) == 0 && GetX6(instruction) == 8) {
goto imm20a;
}
return false;
case M_UNIT:
// M20 x3 == 1 integer chk.s.m
// M21 x3 == 3 floating point chk.s
if (opcode == 1) {
UINT64 const x3 = GetX3(instruction);
if (x3 == 1 || x3 == 3) {
goto imm13_7;
}
}
// M22 x3 == 4 integer chk.a.nc
// M22 x3 == 5 integer chk.a.clr
// M23 x3 == 6 floating point chk.a.nc
// M23 x3 == 7 floating point chk.a.clr
if (opcode == 0) {
UINT64 const x3 = GetX3(instruction);
if (x3 == 4 || x3 == 5 || x3 == 6 || x3 == 7) {
goto imm20b;
}
}
return false;
case I_UNIT:
// I20
if (opcode == 0 && GetX3(instruction) == 1) { // chk.s.i
goto imm13_7;
}
return false;
case B_UNIT:
// B1 B2 B3
// 4 br
// 5 br.call
if (opcode == 4 || opcode == 5) {
goto imm20b;
}
return false;
}
return false;
UINT64 imm;
UINT64 new_instruction;
imm13_7:
imm = SignExtend((GetSignBit(instruction) << 20) | (GetImm13c(instruction) << 7) | GetImm7a(instruction), 21) << 4;
new_instruction = SetSignBit(SetImm13c(SetImm7a(instruction, (extra - dest) >> 4), (extra - dest) >> 11), extra < dest);
goto set_brl;
imm20a:
imm = SignExtend((GetSignBit(instruction) << 20) | GetImm20a(instruction), 21) << 4;
new_instruction = SetSignBit(SetImm20a(instruction, (extra - dest) >> 4), extra < dest);
goto set_brl;
imm20b:
imm = SignExtend((GetSignBit(instruction) << 20) | GetImm20b(instruction), 21) << 4;
new_instruction = SetSignBit(SetImm20b(instruction, (extra - dest) >> 4), extra < dest);
goto set_brl;
set_brl:
if (pBundleExtra != NULL) {
pDst->SetInstruction(slot, new_instruction);
pBundleExtra->SetBrl((size_t)this + imm);
}
return true;
}