|
|
|
|
@ -260,6 +260,15 @@ namespace mir
|
|
|
|
|
std::string g_cached_adrp_symbol;
|
|
|
|
|
bool g_adrp_cache_valid = false;
|
|
|
|
|
|
|
|
|
|
// 帧基址缓存——x13 持有 x29 + g_frame_base_offset,避免重复计算地址
|
|
|
|
|
int g_frame_base_offset = 0;
|
|
|
|
|
bool g_frame_base_valid = false;
|
|
|
|
|
|
|
|
|
|
void InvalidateFrameBase()
|
|
|
|
|
{
|
|
|
|
|
g_frame_base_valid = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InvalidateAdrpCache()
|
|
|
|
|
{
|
|
|
|
|
g_adrp_cache_valid = false;
|
|
|
|
|
@ -270,6 +279,7 @@ namespace mir
|
|
|
|
|
if (amount > 12285)
|
|
|
|
|
{
|
|
|
|
|
InvalidateAdrpCache();
|
|
|
|
|
InvalidateFrameBase();
|
|
|
|
|
os << " movz x13, #" << (amount & 0xFFFF) << "\n";
|
|
|
|
|
if ((amount >> 16) != 0)
|
|
|
|
|
os << " movk x13, #" << ((amount >> 16) & 0xFFFF) << ", lsl #16\n";
|
|
|
|
|
@ -295,9 +305,17 @@ namespace mir
|
|
|
|
|
void EmitAddressFromBase(PhysReg target_xreg, PhysReg base_reg, int offset,
|
|
|
|
|
std::ostream &os)
|
|
|
|
|
{
|
|
|
|
|
if (offset > 12285)
|
|
|
|
|
// 使用 x13 时,ADRP 和帧基址缓存同时失效
|
|
|
|
|
if (target_xreg == PrinterScratchXReg())
|
|
|
|
|
{
|
|
|
|
|
InvalidateAdrpCache();
|
|
|
|
|
InvalidateFrameBase();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (offset > 12285)
|
|
|
|
|
{
|
|
|
|
|
if (target_xreg != PrinterScratchXReg())
|
|
|
|
|
InvalidateAdrpCache();
|
|
|
|
|
os << " movz x13, #" << (offset & 0xFFFF) << "\n";
|
|
|
|
|
if ((offset >> 16) != 0)
|
|
|
|
|
os << " movk x13, #" << ((offset >> 16) & 0xFFFF) << ", lsl #16\n";
|
|
|
|
|
@ -308,7 +326,8 @@ namespace mir
|
|
|
|
|
if (offset < -12285)
|
|
|
|
|
{
|
|
|
|
|
int abs_off = -offset;
|
|
|
|
|
InvalidateAdrpCache();
|
|
|
|
|
if (target_xreg != PrinterScratchXReg())
|
|
|
|
|
InvalidateAdrpCache();
|
|
|
|
|
os << " movz x13, #" << (abs_off & 0xFFFF) << "\n";
|
|
|
|
|
if ((abs_off >> 16) != 0)
|
|
|
|
|
os << " movk x13, #" << ((abs_off >> 16) & 0xFFFF) << ", lsl #16\n";
|
|
|
|
|
@ -341,6 +360,7 @@ namespace mir
|
|
|
|
|
const char *narrow_op = (opcode == Opcode::LoadStack) ? "ldur" : "stur";
|
|
|
|
|
const char *wide_op = (opcode == Opcode::LoadStack) ? "ldr" : "str";
|
|
|
|
|
|
|
|
|
|
// x29 可达的窄范围直接用 ldur/stur
|
|
|
|
|
if (offset >= -256 && offset <= 255)
|
|
|
|
|
{
|
|
|
|
|
os << " " << narrow_op << " ";
|
|
|
|
|
@ -350,7 +370,41 @@ namespace mir
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const PhysReg scratch_xreg = PrinterScratchXReg();
|
|
|
|
|
bool is_32bit = IsWReg(reg.GetReg()) || IsSReg(reg.GetReg());
|
|
|
|
|
|
|
|
|
|
// 尝试帧基址缓存——x13 已持有之前的地址
|
|
|
|
|
if (g_frame_base_valid)
|
|
|
|
|
{
|
|
|
|
|
int diff = offset - g_frame_base_offset;
|
|
|
|
|
|
|
|
|
|
// ldur/stur(范围 ±256)
|
|
|
|
|
if (diff >= -256 && diff <= 255)
|
|
|
|
|
{
|
|
|
|
|
os << " " << narrow_op << " ";
|
|
|
|
|
PrintOperand(reg, os);
|
|
|
|
|
os << ", [" << PhysRegName(scratch_xreg) << ", #" << diff << "]\n";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ldr/str 无符号立即数(正偏移)
|
|
|
|
|
if (diff >= 0)
|
|
|
|
|
{
|
|
|
|
|
int max_imm = is_32bit ? 16380 : 32760;
|
|
|
|
|
int align = is_32bit ? 4 : 8;
|
|
|
|
|
if (diff <= max_imm && diff % align == 0)
|
|
|
|
|
{
|
|
|
|
|
os << " " << wide_op << " ";
|
|
|
|
|
PrintOperand(reg, os);
|
|
|
|
|
os << ", [" << PhysRegName(scratch_xreg) << ", #" << diff << "]\n";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 缓存未命中——完整计算地址到 x13
|
|
|
|
|
EmitAddressFromBase(scratch_xreg, PhysReg::X29, offset, os);
|
|
|
|
|
g_frame_base_offset = offset;
|
|
|
|
|
g_frame_base_valid = true;
|
|
|
|
|
|
|
|
|
|
os << " " << wide_op << " ";
|
|
|
|
|
PrintOperand(reg, os);
|
|
|
|
|
@ -386,6 +440,7 @@ namespace mir
|
|
|
|
|
os << " adrp " << PhysRegName(scratch_xreg) << ", " << asm_symbol << "\n";
|
|
|
|
|
g_cached_adrp_symbol = asm_symbol;
|
|
|
|
|
g_adrp_cache_valid = true;
|
|
|
|
|
InvalidateFrameBase();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
os << " " << (opcode == Opcode::LoadGlobal ? "ldr " : "str ");
|
|
|
|
|
@ -944,6 +999,7 @@ namespace mir
|
|
|
|
|
void PrintAsm(const MachineFunction &function, std::ostream &os)
|
|
|
|
|
{
|
|
|
|
|
g_adrp_cache_valid = false;
|
|
|
|
|
g_frame_base_valid = false;
|
|
|
|
|
const std::string asm_name = NormalizeAsmSymbol(function.GetName());
|
|
|
|
|
|
|
|
|
|
os << " .text\n";
|
|
|
|
|
@ -959,8 +1015,9 @@ namespace mir
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const auto &block = *block_ptr;
|
|
|
|
|
// 每个基本块重置 ADRP 缓存——跨块时 x13 可能已被 call/clobber 破坏
|
|
|
|
|
// 每个基本块重置缓存——跨块时 x13 可能已被 call/clobber 破坏
|
|
|
|
|
g_adrp_cache_valid = false;
|
|
|
|
|
g_frame_base_valid = false;
|
|
|
|
|
PrintBlockLabelRef(function, block.GetLabelId(), os);
|
|
|
|
|
os << ":\n";
|
|
|
|
|
|
|
|
|
|
|