|
|
|
|
@ -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 {
|
|
|
|
|
|