authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-10 18:16:14+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-10 18:16:14+02:00
loga9514ae1732df1fdc142b602e62ab0d12f693afa
treefe15f8544601e0c44b1ac5eea02e6175f1b10d22
parent6a4e445f5aaadf8e87ec08499c84f1d5f279e8b3

x64: handle immediate as RHS of shift bin ops


1 files changed, 35 insertions(+), 15 deletions(-)

src/arch/x86_64/CodeGen.zig+35-15
......@@ -1659,6 +1659,8 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {
16591659 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
16601660 }
16611661
1662 try self.spillRegisters(1, .{.rcx});
1663
16621664 const tag = self.air.instructions.items(.tag)[inst];
16631665 const lhs = try self.resolveInst(bin_op.lhs);
16641666 const rhs = try self.resolveInst(bin_op.rhs);
......@@ -2981,7 +2983,7 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
29812983}
29822984
29832985/// Result is always a register.
2984/// Clobbers .rcx therefore care is needed to spill .rcx upfront.
2986/// Clobbers .rcx for non-immediate rhs, therefore care is needed to spill .rcx upfront.
29852987/// Asserts .rcx is free.
29862988fn genShiftBinOp(
29872989 self: *Self,
......@@ -2999,12 +3001,7 @@ fn genShiftBinOp(
29993001 return self.fail("TODO implement genShiftBinOp for {}", .{lhs_ty.fmtDebug()});
30003002 }
30013003
3002 assert(self.register_manager.isRegFree(.rcx));
3003
3004 try self.register_manager.getReg(.rcx, null);
3005 try self.genSetReg(rhs_ty, .rcx, rhs);
3006 const rcx_lock = self.register_manager.lockRegAssumeUnused(.rcx);
3007 defer self.register_manager.unlockReg(rcx_lock);
3004 assert(rhs_ty.abiSize(self.target.*) == 1);
30083005
30093006 const int_info = lhs_ty.intInfo(self.target.*);
30103007 const signedness = int_info.signedness;
......@@ -3021,6 +3018,29 @@ fn genShiftBinOp(
30213018 };
30223019 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
30233020
3021 const flags: u2 = blk: {
3022 if (rhs.isImmediate()) {
3023 const flags: u2 = switch (rhs.immediate) {
3024 0 => unreachable, // TODO is this valid?
3025 1 => 0b00,
3026 else => 0b10,
3027 };
3028 break :blk flags;
3029 }
3030
3031 assert(self.register_manager.isRegFree(.rcx));
3032
3033 try self.register_manager.getReg(.rcx, null);
3034 try self.genSetReg(rhs_ty, .rcx, rhs);
3035 const rcx_lock = self.register_manager.lockRegAssumeUnused(.rcx);
3036 defer self.register_manager.unlockReg(rcx_lock);
3037
3038 break :blk 0b01;
3039 };
3040 const data: Mir.Inst.Data = if (rhs.isImmediate()) .{
3041 .imm = @intCast(u8, rhs.immediate),
3042 } else undefined;
3043
30243044 const dst: MCValue = blk: {
30253045 if (maybe_inst) |inst| {
30263046 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
......@@ -3040,9 +3060,9 @@ fn genShiftBinOp(
30403060 .tag = .sal,
30413061 .ops = (Mir.Ops{
30423062 .reg1 = dst.register,
3043 .flags = 0b01,
3063 .flags = flags,
30443064 }).encode(),
3045 .data = undefined,
3065 .data = data,
30463066 });
30473067 },
30483068 .unsigned => {
......@@ -3050,9 +3070,9 @@ fn genShiftBinOp(
30503070 .tag = .shl,
30513071 .ops = (Mir.Ops{
30523072 .reg1 = dst.register,
3053 .flags = 0b01,
3073 .flags = flags,
30543074 }).encode(),
3055 .data = undefined,
3075 .data = data,
30563076 });
30573077 },
30583078 },
......@@ -3062,9 +3082,9 @@ fn genShiftBinOp(
30623082 .tag = .sar,
30633083 .ops = (Mir.Ops{
30643084 .reg1 = dst.register,
3065 .flags = 0b01,
3085 .flags = flags,
30663086 }).encode(),
3067 .data = undefined,
3087 .data = data,
30683088 });
30693089 },
30703090 .unsigned => {
......@@ -3072,9 +3092,9 @@ fn genShiftBinOp(
30723092 .tag = .shr,
30733093 .ops = (Mir.Ops{
30743094 .reg1 = dst.register,
3075 .flags = 0b01,
3095 .flags = flags,
30763096 }).encode(),
3077 .data = undefined,
3097 .data = data,
30783098 });
30793099 },
30803100 },