feat(mir)添加Movk指令加载大立即数

feature/mir
mxr 1 day ago
parent 4132f0b5ca
commit 596b0ee334

@ -130,6 +130,9 @@ enum class Opcode {
// ---------- 特殊 ----------
Nop, // 空操作: NOP
Label, // 内联标签,不生成实际指令,仅输出标签名
// 添加
Movk, // movk Rd, #imm16, lsl #shift
};
// ========== 操作数类 ==========

@ -316,6 +316,10 @@ void PrintInstruction(std::ostream& os, const MachineInstr& instr,
case Opcode::Label:
os << ops.at(0).GetLabel() << ":\n";
break;
case Opcode::Movk:
os << " movk " << PhysRegName(ops.at(0).GetReg()) << ", #"
<< ops.at(1).GetImm() << ", lsl #" << ops.at(2).GetImm() << "\n";
break;
default:
os << " // unknown instruction\n";
break;

@ -128,9 +128,34 @@ void EmitValueToReg(const ir::Value* value, PhysReg target,
if (value == nullptr) {
DEBUG_MSG( "EmitValueToReg called with null value\n");
}
// 辅助函数判断32位立即数是否可用单条 movz/movn 编码
auto isLegalMovImm = [](uint32_t imm) -> bool {
// 检查是否可以通过 movz 或 movn 表示16位立即数可左移0/16/32/48位
// 对于32位寄存器只考虑 lsl 0 或 16
if ((imm & 0xFFFF) == imm) return true; // 低16位lsl #0
if ((imm & 0xFFFF0000) == imm) return true; // 高16位lsl #16
// 可选:检查 movn 情况(~imm 满足上述条件),为了简单可不做,直接返回 false
return false;
};
if (auto* constant = dynamic_cast<const ir::ConstantInt*>(value)) {
block.Append(Opcode::MovImm,
{Operand::Reg(target), Operand::Imm(constant->GetValue())});
uint32_t imm = static_cast<uint32_t>(constant->GetValue());
if (isLegalMovImm(imm)) {
block.Append(Opcode::MovImm,
{Operand::Reg(target), Operand::Imm(static_cast<int64_t>(imm))});
} else {
// 分解为 movz (低16位) + movk (高16位)
uint16_t low = imm & 0xFFFF;
uint16_t high = (imm >> 16) & 0xFFFF;
block.Append(Opcode::MovImm,
{Operand::Reg(target), Operand::Imm(low)}); // 先加载低16位
if (high != 0) {
// 使用 Movk 指令写入高16位
block.Append(Opcode::Movk,
{Operand::Reg(target), Operand::Imm(high), Operand::Imm(16)});
}
}
return;
}
// 处理浮点常量
@ -150,8 +175,17 @@ void EmitValueToReg(const ir::Value* value, PhysReg target,
float fval = fconstant->GetValue();
uint32_t int_val = FloatToBits(fval);
// 使用临时寄存器加载常量并存储
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(static_cast<int>(int_val))});
// 同样需要对 int_val 进行大立即数分解
if (isLegalMovImm(int_val)) {
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(static_cast<int64_t>(int_val))});
} else {
uint16_t low = int_val & 0xFFFF;
uint16_t high = (int_val >> 16) & 0xFFFF;
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(low)});
if (high != 0) {
block.Append(Opcode::Movk, {Operand::Reg(PhysReg::W8), Operand::Imm(high), Operand::Imm(16)});
}
}
block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(slot)});
const_cast<ValueSlotMap&>(slots).emplace(value, slot);
} else {

Loading…
Cancel
Save