| ... | ... | @@ -2052,11 +2052,76 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void { |
| 2052 | 2052 | |
| 2053 | 2053 | fn airShr(self: *Self, inst: Air.Inst.Index) !void { |
| 2054 | 2054 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 2055 | | const result: MCValue = if (self.liveness.isUnused(inst)) |
| 2056 | | .dead |
| 2057 | | else |
| 2058 | | return self.fail("TODO implement shr for {}", .{self.target.cpu.arch}); |
| 2059 | | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 2055 | |
| 2056 | if (self.liveness.isUnused(inst)) { |
| 2057 | return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 2058 | } |
| 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 | } |
| 2061 | 2126 | |
| 2062 | 2127 | fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void { |