emit_x64: bug: OP m/r64, imm32 form instructions sign-extend their immediate on x64
This commit is contained in:
parent
989d036e65
commit
e4615a4562
4 changed files with 29 additions and 8 deletions
|
@ -180,8 +180,8 @@ void A64EmitX64::EmitA64SetX(A64EmitContext& ctx, IR::Inst* inst) {
|
||||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
A64::Reg reg = inst->GetArg(0).GetA64RegRef();
|
A64::Reg reg = inst->GetArg(0).GetA64RegRef();
|
||||||
auto addr = qword[r15 + offsetof(A64JitState, reg) + sizeof(u64) * static_cast<size_t>(reg)];
|
auto addr = qword[r15 + offsetof(A64JitState, reg) + sizeof(u64) * static_cast<size_t>(reg)];
|
||||||
if (args[1].FitsInImmediateU32()) {
|
if (args[1].FitsInImmediateS32()) {
|
||||||
code->mov(addr, args[1].GetImmediateU32());
|
code->mov(addr, args[1].GetImmediateS32());
|
||||||
} else if (args[1].IsInXmm()) {
|
} else if (args[1].IsInXmm()) {
|
||||||
Xbyak::Xmm to_store = ctx.reg_alloc.UseXmm(args[1]);
|
Xbyak::Xmm to_store = ctx.reg_alloc.UseXmm(args[1]);
|
||||||
code->movq(addr, to_store);
|
code->movq(addr, to_store);
|
||||||
|
|
|
@ -993,8 +993,8 @@ void EmitX64<JST>::EmitAnd64(EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
|
||||||
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
|
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
|
||||||
|
|
||||||
if (args[1].FitsInImmediateU32()) {
|
if (args[1].FitsInImmediateS32()) {
|
||||||
u32 op_arg = args[1].GetImmediateU32();
|
u32 op_arg = u32(args[1].GetImmediateS32());
|
||||||
|
|
||||||
code->and_(result, op_arg);
|
code->and_(result, op_arg);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1033,8 +1033,8 @@ void EmitX64<JST>::EmitEor64(EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
|
||||||
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
|
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
|
||||||
|
|
||||||
if (args[1].FitsInImmediateU32()) {
|
if (args[1].FitsInImmediateS32()) {
|
||||||
u32 op_arg = args[1].GetImmediateU32();
|
u32 op_arg = u32(args[1].GetImmediateS32());
|
||||||
|
|
||||||
code->xor_(result, op_arg);
|
code->xor_(result, op_arg);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1073,8 +1073,8 @@ void EmitX64<JST>::EmitOr64(EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
|
||||||
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
|
Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(args[0]);
|
||||||
|
|
||||||
if (args[1].FitsInImmediateU32()) {
|
if (args[1].FitsInImmediateS32()) {
|
||||||
u32 op_arg = args[1].GetImmediateU32();
|
u32 op_arg = u32(args[1].GetImmediateS32());
|
||||||
|
|
||||||
code->or_(result, op_arg);
|
code->or_(result, op_arg);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -107,6 +107,13 @@ bool Argument::FitsInImmediateU32() const {
|
||||||
return imm < 0x100000000;
|
return imm < 0x100000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Argument::FitsInImmediateS32() const {
|
||||||
|
if (!IsImmediate())
|
||||||
|
return false;
|
||||||
|
s64 imm = static_cast<s64>(ImmediateToU64(value));
|
||||||
|
return -s64(0x80000000) <= imm && imm <= s64(0x7FFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
bool Argument::GetImmediateU1() const {
|
bool Argument::GetImmediateU1() const {
|
||||||
return value.GetU1();
|
return value.GetU1();
|
||||||
}
|
}
|
||||||
|
@ -129,19 +136,31 @@ u32 Argument::GetImmediateU32() const {
|
||||||
return u32(imm);
|
return u32(imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 Argument::GetImmediateS32() const {
|
||||||
|
ASSERT(FitsInImmediateS32());
|
||||||
|
u64 imm = ImmediateToU64(value);
|
||||||
|
return imm;
|
||||||
|
}
|
||||||
|
|
||||||
u64 Argument::GetImmediateU64() const {
|
u64 Argument::GetImmediateU64() const {
|
||||||
return ImmediateToU64(value);
|
return ImmediateToU64(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Argument::IsInGpr() const {
|
bool Argument::IsInGpr() const {
|
||||||
|
if (IsImmediate())
|
||||||
|
return false;
|
||||||
return HostLocIsGPR(*reg_alloc.ValueLocation(value.GetInst()));
|
return HostLocIsGPR(*reg_alloc.ValueLocation(value.GetInst()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Argument::IsInXmm() const {
|
bool Argument::IsInXmm() const {
|
||||||
|
if (IsImmediate())
|
||||||
|
return false;
|
||||||
return HostLocIsXMM(*reg_alloc.ValueLocation(value.GetInst()));
|
return HostLocIsXMM(*reg_alloc.ValueLocation(value.GetInst()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Argument::IsInMemory() const {
|
bool Argument::IsInMemory() const {
|
||||||
|
if (IsImmediate())
|
||||||
|
return false;
|
||||||
return HostLocIsSpill(*reg_alloc.ValueLocation(value.GetInst()));
|
return HostLocIsSpill(*reg_alloc.ValueLocation(value.GetInst()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,11 +57,13 @@ public:
|
||||||
bool IsImmediate() const;
|
bool IsImmediate() const;
|
||||||
|
|
||||||
bool FitsInImmediateU32() const;
|
bool FitsInImmediateU32() const;
|
||||||
|
bool FitsInImmediateS32() const;
|
||||||
|
|
||||||
bool GetImmediateU1() const;
|
bool GetImmediateU1() const;
|
||||||
u8 GetImmediateU8() const;
|
u8 GetImmediateU8() const;
|
||||||
u16 GetImmediateU16() const;
|
u16 GetImmediateU16() const;
|
||||||
u32 GetImmediateU32() const;
|
u32 GetImmediateU32() const;
|
||||||
|
u64 GetImmediateS32() const;
|
||||||
u64 GetImmediateU64() const;
|
u64 GetImmediateU64() const;
|
||||||
|
|
||||||
/// Is this value currently in a GPR?
|
/// Is this value currently in a GPR?
|
||||||
|
|
Loading…
Reference in a new issue