From 5ba66911faf71cc6bab7f9329474ed15804e783d Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Sun, 20 Feb 2022 20:46:39 +0100 Subject: [PATCH] x64: add basic impl of shl for integers --- src/arch/x86_64/CodeGen.zig | 57 +++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index ef1425cdcc..9c2c7ba04a 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -1605,11 +1605,58 @@ fn airXor(self: *Self, inst: Air.Inst.Index) !void { fn airShl(self: *Self, inst: Air.Inst.Index) !void { const bin_op = self.air.instructions.items(.data)[inst].bin_op; - const result: MCValue = if (self.liveness.isUnused(inst)) - .dead - else - return self.fail("TODO implement shl for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); + if (self.liveness.isUnused(inst)) { + return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); + } + + const ty = self.air.typeOfIndex(inst); + const tag = self.air.instructions.items(.tag)[inst]; + switch (tag) { + .shl_exact => return self.fail("TODO implement {} for type {}", .{ tag, ty }), + .shl => {}, + else => unreachable, + } + + if (ty.zigTypeTag() != .Int) { + return self.fail("TODO implement .shl for type {}", .{ty}); + } + if (ty.abiSize(self.target.*) > 8) { + return self.fail("TODO implement .shl for integers larger than 8 bytes", .{}); + } + + // TODO look into reusing the operands + // TODO audit register allocation mechanics + const shift = try self.resolveInst(bin_op.rhs); + const shift_ty = self.air.typeOf(bin_op.rhs); + + blk: { + switch (shift) { + .register => |reg| { + if (reg.to64() == .rcx) break :blk; + }, + else => {}, + } + try self.register_manager.getReg(.rcx, null); + try self.genSetReg(shift_ty, .rcx, shift); + } + self.register_manager.freezeRegs(&.{.rcx}); + defer self.register_manager.unfreezeRegs(&.{.rcx}); + + const value = try self.resolveInst(bin_op.lhs); + value.freezeIfRegister(&self.register_manager); + defer value.unfreezeIfRegister(&self.register_manager); + + const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ty, value); + _ = try self.addInst(.{ + .tag = .sal, + .ops = (Mir.Ops{ + .reg1 = dst_mcv.register, + .flags = 0b01, + }).encode(), + .data = undefined, + }); + + return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none }); } fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {