x64: handle immediate as RHS of shift bin ops

This commit is contained in:
Jakub Konka 2022-05-10 18:16:14 +02:00
parent 6a4e445f5a
commit a9514ae173

View File

@ -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,
});
},
},