| ... | ... | @@ -1254,10 +1254,92 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1254 | 1254 | |
| 1255 | 1255 | fn airDiv(self: *Self, inst: Air.Inst.Index) !void { |
| 1256 | 1256 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1257 | | const result: MCValue = if (self.liveness.isUnused(inst)) |
| 1258 | | .dead |
| 1259 | | else |
| 1260 | | return self.fail("TODO implement div for {}", .{self.target.cpu.arch}); |
| 1257 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1258 | const dst_ty = self.air.typeOfIndex(inst); |
| 1259 | const tag = self.air.instructions.items(.tag)[inst]; |
| 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 | 1343 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1262 | 1344 | } |
| 1263 | 1345 | |
| ... | ... | @@ -4126,7 +4208,7 @@ fn genInlineMemset( |
| 4126 | 4208 | } |
| 4127 | 4209 | |
| 4128 | 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 | 4212 | switch (mcv) { |
| 4131 | 4213 | .dead => unreachable, |
| 4132 | 4214 | .ptr_stack_offset => |off| { |
| ... | ... | @@ -4136,7 +4218,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 4136 | 4218 | _ = try self.addInst(.{ |
| 4137 | 4219 | .tag = .lea, |
| 4138 | 4220 | .ops = (Mir.Ops{ |
| 4139 | | .reg1 = registerAlias(reg, @intCast(u32, abi_size)), |
| 4221 | .reg1 = registerAlias(reg, abi_size), |
| 4140 | 4222 | .reg2 = .rbp, |
| 4141 | 4223 | }).encode(), |
| 4142 | 4224 | .data = .{ .imm = @bitCast(u32, -off) }, |
| ... | ... | @@ -4202,7 +4284,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 4202 | 4284 | _ = try self.addInst(.{ |
| 4203 | 4285 | .tag = .mov, |
| 4204 | 4286 | .ops = (Mir.Ops{ |
| 4205 | | .reg1 = registerAlias(reg, @intCast(u32, abi_size)), |
| 4287 | .reg1 = registerAlias(reg, abi_size), |
| 4206 | 4288 | }).encode(), |
| 4207 | 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 | 4354 | _ = try self.addInst(.{ |
| 4273 | 4355 | .tag = .mov, |
| 4274 | 4356 | .ops = (Mir.Ops{ |
| 4275 | | .reg1 = registerAlias(reg, @divExact(src_reg.size(), 8)), |
| 4276 | | .reg2 = src_reg, |
| 4357 | .reg1 = registerAlias(reg, abi_size), |
| 4358 | .reg2 = registerAlias(src_reg, abi_size), |
| 4277 | 4359 | }).encode(), |
| 4278 | 4360 | .data = undefined, |
| 4279 | 4361 | }); |
| ... | ... | @@ -4399,7 +4481,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 4399 | 4481 | _ = try self.addInst(.{ |
| 4400 | 4482 | .tag = .mov, |
| 4401 | 4483 | .ops = (Mir.Ops{ |
| 4402 | | .reg1 = registerAlias(reg, @intCast(u32, abi_size)), |
| 4484 | .reg1 = registerAlias(reg, abi_size), |
| 4403 | 4485 | .reg2 = .rbp, |
| 4404 | 4486 | .flags = 0b01, |
| 4405 | 4487 | }).encode(), |