| ... | @@ -1254,10 +1254,92 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1254,10 +1254,92 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1254 | | 1254 | |
| 1255 | fn airDiv(self: *Self, inst: Air.Inst.Index) !void { | 1255 | fn airDiv(self: *Self, inst: Air.Inst.Index) !void { |
| 1256 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1256 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1257 | const result: MCValue = if (self.liveness.isUnused(inst)) | 1257 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1258 | .dead | 1258 | const dst_ty = self.air.typeOfIndex(inst); |
| 1259 | else | 1259 | const tag = self.air.instructions.items(.tag)[inst]; |
| 1260 | return self.fail("TODO implement div for {}", .{self.target.cpu.arch}); | 1260 | switch (tag) { |
| | 1261 | .div_exact => {}, |
| | 1262 | .div_trunc, .div_floor, .div_float => return self.fail("TODO implement {}", .{tag}), |
| | 1263 | else => unreachable, |
| | 1264 | } |
| | 1265 | |
| | 1266 | if (dst_ty.zigTypeTag() != .Int) { |
| | 1267 | return self.fail("TODO implement {} for operands of type {}", .{ tag, dst_ty.zigTypeTag() }); |
| | 1268 | } |
| | 1269 | |
| | 1270 | const signedness = dst_ty.intInfo(self.target.*).signedness; |
| | 1271 | const ty = if (signedness == .signed) Type.isize else dst_ty; |
| | 1272 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| | 1273 | |
| | 1274 | const lhs = try self.resolveInst(bin_op.lhs); |
| | 1275 | blk: { |
| | 1276 | switch (lhs) { |
| | 1277 | .register => |reg| { |
| | 1278 | if (reg.to64() == .rax) break :blk; |
| | 1279 | }, |
| | 1280 | else => {}, |
| | 1281 | } |
| | 1282 | try self.register_manager.getReg(.rax, inst); // track inst -> rax in register manager |
| | 1283 | try self.genSetReg(ty, .rax, lhs); |
| | 1284 | } |
| | 1285 | if (signedness == .signed) { |
| | 1286 | _ = try self.addInst(.{ |
| | 1287 | .tag = .cwd, |
| | 1288 | .ops = (Mir.Ops{ |
| | 1289 | .flags = 0b11, |
| | 1290 | }).encode(), |
| | 1291 | .data = undefined, |
| | 1292 | }); |
| | 1293 | } |
| | 1294 | const dst_mcv = MCValue{ .register = registerAlias(.rax, abi_size) }; |
| | 1295 | |
| | 1296 | try self.register_manager.getReg(.rdx, null); |
| | 1297 | self.register_manager.freezeRegs(&.{ .rax, .rdx }); |
| | 1298 | defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx }); |
| | 1299 | |
| | 1300 | const rhs = try self.resolveInst(bin_op.rhs); |
| | 1301 | const divisor = blk: { |
| | 1302 | switch (rhs) { |
| | 1303 | .register, .stack_offset => break :blk rhs, |
| | 1304 | else => { |
| | 1305 | const reg = try self.copyToTmpRegister(ty, rhs); |
| | 1306 | break :blk MCValue{ .register = reg }; |
| | 1307 | }, |
| | 1308 | } |
| | 1309 | }; |
| | 1310 | |
| | 1311 | switch (divisor) { |
| | 1312 | .register => |reg| { |
| | 1313 | _ = try self.addInst(.{ |
| | 1314 | .tag = .idiv, |
| | 1315 | .ops = (Mir.Ops{ |
| | 1316 | .reg1 = registerAlias(reg, abi_size), |
| | 1317 | }).encode(), |
| | 1318 | .data = undefined, |
| | 1319 | }); |
| | 1320 | }, |
| | 1321 | .stack_offset => |off| { |
| | 1322 | const flags: u2 = switch (abi_size) { |
| | 1323 | 1 => 0b00, |
| | 1324 | 2 => 0b01, |
| | 1325 | 4 => 0b10, |
| | 1326 | 8 => 0b11, |
| | 1327 | else => unreachable, |
| | 1328 | }; |
| | 1329 | _ = try self.addInst(.{ |
| | 1330 | .tag = .idiv, |
| | 1331 | .ops = (Mir.Ops{ |
| | 1332 | .reg2 = .rbp, |
| | 1333 | .flags = flags, |
| | 1334 | }).encode(), |
| | 1335 | .data = .{ .imm = @bitCast(u32, -off) }, |
| | 1336 | }); |
| | 1337 | }, |
| | 1338 | else => unreachable, |
| | 1339 | } |
| | 1340 | |
| | 1341 | break :result dst_mcv; |
| | 1342 | }; |
| 1261 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1343 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1262 | } | 1344 | } |
| 1263 | | 1345 | |
| ... | @@ -4126,7 +4208,7 @@ fn genInlineMemset( | ... | @@ -4126,7 +4208,7 @@ fn genInlineMemset( |
| 4126 | } | 4208 | } |
| 4127 | | 4209 | |
| 4128 | fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { | 4210 | fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void { |
| 4129 | const abi_size = ty.abiSize(self.target.*); | 4211 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 4130 | switch (mcv) { | 4212 | switch (mcv) { |
| 4131 | .dead => unreachable, | 4213 | .dead => unreachable, |
| 4132 | .ptr_stack_offset => |off| { | 4214 | .ptr_stack_offset => |off| { |
| ... | @@ -4136,7 +4218,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -4136,7 +4218,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 4136 | _ = try self.addInst(.{ | 4218 | _ = try self.addInst(.{ |
| 4137 | .tag = .lea, | 4219 | .tag = .lea, |
| 4138 | .ops = (Mir.Ops{ | 4220 | .ops = (Mir.Ops{ |
| 4139 | .reg1 = registerAlias(reg, @intCast(u32, abi_size)), | 4221 | .reg1 = registerAlias(reg, abi_size), |
| 4140 | .reg2 = .rbp, | 4222 | .reg2 = .rbp, |
| 4141 | }).encode(), | 4223 | }).encode(), |
| 4142 | .data = .{ .imm = @bitCast(u32, -off) }, | 4224 | .data = .{ .imm = @bitCast(u32, -off) }, |
| ... | @@ -4202,7 +4284,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -4202,7 +4284,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 4202 | _ = try self.addInst(.{ | 4284 | _ = try self.addInst(.{ |
| 4203 | .tag = .mov, | 4285 | .tag = .mov, |
| 4204 | .ops = (Mir.Ops{ | 4286 | .ops = (Mir.Ops{ |
| 4205 | .reg1 = registerAlias(reg, @intCast(u32, abi_size)), | 4287 | .reg1 = registerAlias(reg, abi_size), |
| 4206 | }).encode(), | 4288 | }).encode(), |
| 4207 | .data = .{ .imm = @truncate(u32, x) }, | 4289 | .data = .{ .imm = @truncate(u32, x) }, |
| 4208 | }); | 4290 | }); |
| ... | @@ -4272,8 +4354,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -4272,8 +4354,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 4272 | _ = try self.addInst(.{ | 4354 | _ = try self.addInst(.{ |
| 4273 | .tag = .mov, | 4355 | .tag = .mov, |
| 4274 | .ops = (Mir.Ops{ | 4356 | .ops = (Mir.Ops{ |
| 4275 | .reg1 = registerAlias(reg, @divExact(src_reg.size(), 8)), | 4357 | .reg1 = registerAlias(reg, abi_size), |
| 4276 | .reg2 = src_reg, | 4358 | .reg2 = registerAlias(src_reg, abi_size), |
| 4277 | }).encode(), | 4359 | }).encode(), |
| 4278 | .data = undefined, | 4360 | .data = undefined, |
| 4279 | }); | 4361 | }); |
| ... | @@ -4399,7 +4481,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -4399,7 +4481,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 4399 | _ = try self.addInst(.{ | 4481 | _ = try self.addInst(.{ |
| 4400 | .tag = .mov, | 4482 | .tag = .mov, |
| 4401 | .ops = (Mir.Ops{ | 4483 | .ops = (Mir.Ops{ |
| 4402 | .reg1 = registerAlias(reg, @intCast(u32, abi_size)), | 4484 | .reg1 = registerAlias(reg, abi_size), |
| 4403 | .reg2 = .rbp, | 4485 | .reg2 = .rbp, |
| 4404 | .flags = 0b01, | 4486 | .flags = 0b01, |
| 4405 | }).encode(), | 4487 | }).encode(), |