authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-09 17:39:19+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-09 17:39:19+02:00
log9c3d24ea0bffa53fb08a73493d72a6a0866f6432
tree8d9296e6185b8a483e69e13ba55236158472c2e7
parentd7f8368da86241f47e97257e737b6fb14bf5f773

x64: add naive impl of shr


2 files changed, 70 insertions(+), 7 deletions(-)

src/arch/x86_64/CodeGen.zig+70-5
...@@ -2052,11 +2052,76 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -2052,11 +2052,76 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
20522052
2053fn airShr(self: *Self, inst: Air.Inst.Index) !void {2053fn airShr(self: *Self, inst: Air.Inst.Index) !void {
2054 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2054 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2055 const result: MCValue = if (self.liveness.isUnused(inst))2055
2056 .dead2056 if (self.liveness.isUnused(inst)) {
2057 else2057 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
2058 return self.fail("TODO implement shr for {}", .{self.target.cpu.arch});2058 }
2059 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2059
2060 const ty = self.air.typeOfIndex(inst);
2061 const tag = self.air.instructions.items(.tag)[inst];
2062 switch (tag) {
2063 .shr_exact => return self.fail("TODO implement shr_exact for type {}", .{ty.fmtDebug()}),
2064 .shr => {},
2065 else => unreachable,
2066 }
2067
2068 if (ty.zigTypeTag() != .Int) {
2069 return self.fail("TODO implement shr for type {}", .{ty.fmtDebug()});
2070 }
2071 if (ty.abiSize(self.target.*) > 8) {
2072 return self.fail("TODO implement shr for integers larger than 8 bytes", .{});
2073 }
2074
2075 // TODO look into reusing the operands
2076 // TODO audit register allocation mechanics
2077 const shift = try self.resolveInst(bin_op.rhs);
2078 const shift_ty = self.air.typeOf(bin_op.rhs);
2079
2080 blk: {
2081 switch (shift) {
2082 .register => |reg| {
2083 if (reg.to64() == .rcx) break :blk;
2084 },
2085 else => {},
2086 }
2087 try self.register_manager.getReg(.rcx, null);
2088 try self.genSetReg(shift_ty, .rcx, shift);
2089 }
2090 const rcx_lock = self.register_manager.lockRegAssumeUnused(.rcx);
2091 defer self.register_manager.unlockReg(rcx_lock);
2092
2093 const value = try self.resolveInst(bin_op.lhs);
2094 const value_lock: ?RegisterLock = switch (value) {
2095 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
2096 else => null,
2097 };
2098 defer if (value_lock) |lock| self.register_manager.unlockReg(lock);
2099
2100 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ty, value);
2101 switch (ty.intInfo(self.target.*).signedness) {
2102 .signed => {
2103 _ = try self.addInst(.{
2104 .tag = .sar,
2105 .ops = (Mir.Ops{
2106 .reg1 = dst_mcv.register,
2107 .flags = 0b01,
2108 }).encode(),
2109 .data = undefined,
2110 });
2111 },
2112 .unsigned => {
2113 _ = try self.addInst(.{
2114 .tag = .shr,
2115 .ops = (Mir.Ops{
2116 .reg1 = dst_mcv.register,
2117 .flags = 0b01,
2118 }).encode(),
2119 .data = undefined,
2120 });
2121 },
2122 }
2123
2124 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
2060}2125}
20612126
2062fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {2127fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
test/behavior/math.zig-2
...@@ -570,8 +570,6 @@ test "bit shift a u1" {...@@ -570,8 +570,6 @@ test "bit shift a u1" {
570}570}
571571
572test "truncating shift right" {572test "truncating shift right" {
573 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
574
575 try testShrTrunc(maxInt(u16));573 try testShrTrunc(maxInt(u16));
576 comptime try testShrTrunc(maxInt(u16));574 comptime try testShrTrunc(maxInt(u16));
577}575}