mirror of
https://github.com/ziglang/zig.git
synced 2026-02-07 15:07:12 +00:00
x64: handle immediate as RHS of shift bin ops
This commit is contained in:
parent
6a4e445f5a
commit
a9514ae173
@ -1659,6 +1659,8 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {
|
||||
return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
|
||||
}
|
||||
|
||||
try self.spillRegisters(1, .{.rcx});
|
||||
|
||||
const tag = self.air.instructions.items(.tag)[inst];
|
||||
const lhs = try self.resolveInst(bin_op.lhs);
|
||||
const rhs = try self.resolveInst(bin_op.rhs);
|
||||
@ -2981,7 +2983,7 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
}
|
||||
|
||||
/// Result is always a register.
|
||||
/// Clobbers .rcx therefore care is needed to spill .rcx upfront.
|
||||
/// Clobbers .rcx for non-immediate rhs, therefore care is needed to spill .rcx upfront.
|
||||
/// Asserts .rcx is free.
|
||||
fn genShiftBinOp(
|
||||
self: *Self,
|
||||
@ -2999,12 +3001,7 @@ fn genShiftBinOp(
|
||||
return self.fail("TODO implement genShiftBinOp for {}", .{lhs_ty.fmtDebug()});
|
||||
}
|
||||
|
||||
assert(self.register_manager.isRegFree(.rcx));
|
||||
|
||||
try self.register_manager.getReg(.rcx, null);
|
||||
try self.genSetReg(rhs_ty, .rcx, rhs);
|
||||
const rcx_lock = self.register_manager.lockRegAssumeUnused(.rcx);
|
||||
defer self.register_manager.unlockReg(rcx_lock);
|
||||
assert(rhs_ty.abiSize(self.target.*) == 1);
|
||||
|
||||
const int_info = lhs_ty.intInfo(self.target.*);
|
||||
const signedness = int_info.signedness;
|
||||
@ -3021,6 +3018,29 @@ fn genShiftBinOp(
|
||||
};
|
||||
defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
|
||||
|
||||
const flags: u2 = blk: {
|
||||
if (rhs.isImmediate()) {
|
||||
const flags: u2 = switch (rhs.immediate) {
|
||||
0 => unreachable, // TODO is this valid?
|
||||
1 => 0b00,
|
||||
else => 0b10,
|
||||
};
|
||||
break :blk flags;
|
||||
}
|
||||
|
||||
assert(self.register_manager.isRegFree(.rcx));
|
||||
|
||||
try self.register_manager.getReg(.rcx, null);
|
||||
try self.genSetReg(rhs_ty, .rcx, rhs);
|
||||
const rcx_lock = self.register_manager.lockRegAssumeUnused(.rcx);
|
||||
defer self.register_manager.unlockReg(rcx_lock);
|
||||
|
||||
break :blk 0b01;
|
||||
};
|
||||
const data: Mir.Inst.Data = if (rhs.isImmediate()) .{
|
||||
.imm = @intCast(u8, rhs.immediate),
|
||||
} else undefined;
|
||||
|
||||
const dst: MCValue = blk: {
|
||||
if (maybe_inst) |inst| {
|
||||
const bin_op = self.air.instructions.items(.data)[inst].bin_op;
|
||||
@ -3040,9 +3060,9 @@ fn genShiftBinOp(
|
||||
.tag = .sal,
|
||||
.ops = (Mir.Ops{
|
||||
.reg1 = dst.register,
|
||||
.flags = 0b01,
|
||||
.flags = flags,
|
||||
}).encode(),
|
||||
.data = undefined,
|
||||
.data = data,
|
||||
});
|
||||
},
|
||||
.unsigned => {
|
||||
@ -3050,9 +3070,9 @@ fn genShiftBinOp(
|
||||
.tag = .shl,
|
||||
.ops = (Mir.Ops{
|
||||
.reg1 = dst.register,
|
||||
.flags = 0b01,
|
||||
.flags = flags,
|
||||
}).encode(),
|
||||
.data = undefined,
|
||||
.data = data,
|
||||
});
|
||||
},
|
||||
},
|
||||
@ -3062,9 +3082,9 @@ fn genShiftBinOp(
|
||||
.tag = .sar,
|
||||
.ops = (Mir.Ops{
|
||||
.reg1 = dst.register,
|
||||
.flags = 0b01,
|
||||
.flags = flags,
|
||||
}).encode(),
|
||||
.data = undefined,
|
||||
.data = data,
|
||||
});
|
||||
},
|
||||
.unsigned => {
|
||||
@ -3072,9 +3092,9 @@ fn genShiftBinOp(
|
||||
.tag = .shr,
|
||||
.ops = (Mir.Ops{
|
||||
.reg1 = dst.register,
|
||||
.flags = 0b01,
|
||||
.flags = flags,
|
||||
}).encode(),
|
||||
.data = undefined,
|
||||
.data = data,
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user