authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-08 06:51:05-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-08 07:36:20-04:00
logecb5feaf94bf49dc4c180f09c170223d6c1898b3
tree9b168cfd880fb316f86fba14b3773297745e3ba3
parent6c14eb2863c7c00f809c5e447ceb8186b55f2eef

x86_64: continue to optimize mir tag usage

Migrate mnemonic literals to tuples that represent the compressed storage. 225 tags left in use, many tags left to compress.

3 files changed, 870 insertions(+), 708 deletions(-)

src/arch/x86_64/CodeGen.zig+802-667
......@@ -1167,11 +1167,13 @@ fn asmPlaceholder(self: *Self) !Mir.Inst.Index {
11671167 });
11681168}
11691169
1170fn asmOpOnly(self: *Self, tag: Mir.Inst.Tag) !void {
1170fn asmOpOnly(self: *Self, tag: Mir.Inst.FixedTag) !void {
11711171 _ = try self.addInst(.{
1172 .tag = tag,
1172 .tag = tag[1],
11731173 .ops = .none,
1174 .data = undefined,
1174 .data = .{ .none = .{
1175 .fixes = tag[0],
1176 } },
11751177 });
11761178}
11771179
......@@ -1183,22 +1185,26 @@ fn asmPseudo(self: *Self, ops: Mir.Inst.Ops) !void {
11831185 });
11841186}
11851187
1186fn asmRegister(self: *Self, tag: Mir.Inst.Tag, reg: Register) !void {
1188fn asmRegister(self: *Self, tag: Mir.Inst.FixedTag, reg: Register) !void {
11871189 _ = try self.addInst(.{
1188 .tag = tag,
1190 .tag = tag[1],
11891191 .ops = .r,
1190 .data = .{ .r = .{ .r1 = reg } },
1192 .data = .{ .r = .{
1193 .fixes = tag[0],
1194 .r1 = reg,
1195 } },
11911196 });
11921197}
11931198
1194fn asmImmediate(self: *Self, tag: Mir.Inst.Tag, imm: Immediate) !void {
1199fn asmImmediate(self: *Self, tag: Mir.Inst.FixedTag, imm: Immediate) !void {
11951200 _ = try self.addInst(.{
1196 .tag = tag,
1201 .tag = tag[1],
11971202 .ops = switch (imm) {
11981203 .signed => .i_s,
11991204 .unsigned => .i_u,
12001205 },
12011206 .data = .{ .i = .{
1207 .fixes = tag[0],
12021208 .i = switch (imm) {
12031209 .signed => |s| @bitCast(u32, s),
12041210 .unsigned => |u| @intCast(u32, u),
......@@ -1207,24 +1213,29 @@ fn asmImmediate(self: *Self, tag: Mir.Inst.Tag, imm: Immediate) !void {
12071213 });
12081214}
12091215
1210fn asmRegisterRegister(self: *Self, tag: Mir.Inst.Tag, reg1: Register, reg2: Register) !void {
1216fn asmRegisterRegister(self: *Self, tag: Mir.Inst.FixedTag, reg1: Register, reg2: Register) !void {
12111217 _ = try self.addInst(.{
1212 .tag = tag,
1218 .tag = tag[1],
12131219 .ops = .rr,
1214 .data = .{ .rr = .{ .r1 = reg1, .r2 = reg2 } },
1220 .data = .{ .rr = .{
1221 .fixes = tag[0],
1222 .r1 = reg1,
1223 .r2 = reg2,
1224 } },
12151225 });
12161226}
12171227
1218fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Immediate) !void {
1228fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, imm: Immediate) !void {
12191229 const ops: Mir.Inst.Ops = switch (imm) {
12201230 .signed => .ri_s,
12211231 .unsigned => |u| if (math.cast(u32, u)) |_| .ri_u else .ri64,
12221232 };
12231233 _ = try self.addInst(.{
1224 .tag = tag,
1234 .tag = tag[1],
12251235 .ops = ops,
12261236 .data = switch (ops) {
12271237 .ri_s, .ri_u => .{ .ri = .{
1238 .fixes = tag[0],
12281239 .r1 = reg,
12291240 .i = switch (imm) {
12301241 .signed => |s| @bitCast(u32, s),
......@@ -1232,6 +1243,7 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Imme
12321243 },
12331244 } },
12341245 .ri64 => .{ .rx = .{
1246 .fixes = tag[0],
12351247 .r1 = reg,
12361248 .payload = try self.addExtra(Mir.Imm64.encode(imm.unsigned)),
12371249 } },
......@@ -1242,47 +1254,59 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Imme
12421254
12431255fn asmRegisterRegisterRegister(
12441256 self: *Self,
1245 tag: Mir.Inst.Tag,
1257 tag: Mir.Inst.FixedTag,
12461258 reg1: Register,
12471259 reg2: Register,
12481260 reg3: Register,
12491261) !void {
12501262 _ = try self.addInst(.{
1251 .tag = tag,
1263 .tag = tag[1],
12521264 .ops = .rrr,
1253 .data = .{ .rrr = .{ .r1 = reg1, .r2 = reg2, .r3 = reg3 } },
1265 .data = .{ .rrr = .{
1266 .fixes = tag[0],
1267 .r1 = reg1,
1268 .r2 = reg2,
1269 .r3 = reg3,
1270 } },
12541271 });
12551272}
12561273
12571274fn asmRegisterRegisterRegisterImmediate(
12581275 self: *Self,
1259 tag: Mir.Inst.Tag,
1276 tag: Mir.Inst.FixedTag,
12601277 reg1: Register,
12611278 reg2: Register,
12621279 reg3: Register,
12631280 imm: Immediate,
12641281) !void {
12651282 _ = try self.addInst(.{
1266 .tag = tag,
1283 .tag = tag[1],
12671284 .ops = .rrri,
1268 .data = .{ .rrri = .{ .r1 = reg1, .r2 = reg2, .r3 = reg3, .i = @intCast(u8, imm.unsigned) } },
1285 .data = .{ .rrri = .{
1286 .fixes = tag[0],
1287 .r1 = reg1,
1288 .r2 = reg2,
1289 .r3 = reg3,
1290 .i = @intCast(u8, imm.unsigned),
1291 } },
12691292 });
12701293}
12711294
12721295fn asmRegisterRegisterImmediate(
12731296 self: *Self,
1274 tag: Mir.Inst.Tag,
1297 tag: Mir.Inst.FixedTag,
12751298 reg1: Register,
12761299 reg2: Register,
12771300 imm: Immediate,
12781301) !void {
12791302 _ = try self.addInst(.{
1280 .tag = tag,
1303 .tag = tag[1],
12811304 .ops = switch (imm) {
12821305 .signed => .rri_s,
12831306 .unsigned => .rri_u,
12841307 },
12851308 .data = .{ .rri = .{
1309 .fixes = tag[0],
12861310 .r1 = reg1,
12871311 .r2 = reg2,
12881312 .i = switch (imm) {
......@@ -1295,19 +1319,20 @@ fn asmRegisterRegisterImmediate(
12951319
12961320fn asmRegisterRegisterMemory(
12971321 self: *Self,
1298 tag: Mir.Inst.Tag,
1322 tag: Mir.Inst.FixedTag,
12991323 reg1: Register,
13001324 reg2: Register,
13011325 m: Memory,
13021326) !void {
13031327 _ = try self.addInst(.{
1304 .tag = tag,
1328 .tag = tag[1],
13051329 .ops = switch (m) {
13061330 .sib => .rrm_sib,
13071331 .rip => .rrm_rip,
13081332 else => unreachable,
13091333 },
13101334 .data = .{ .rrx = .{
1335 .fixes = tag[0],
13111336 .r1 = reg1,
13121337 .r2 = reg2,
13131338 .payload = switch (m) {
......@@ -1319,15 +1344,16 @@ fn asmRegisterRegisterMemory(
13191344 });
13201345}
13211346
1322fn asmMemory(self: *Self, tag: Mir.Inst.Tag, m: Memory) !void {
1347fn asmMemory(self: *Self, tag: Mir.Inst.FixedTag, m: Memory) !void {
13231348 _ = try self.addInst(.{
1324 .tag = tag,
1349 .tag = tag[1],
13251350 .ops = switch (m) {
13261351 .sib => .m_sib,
13271352 .rip => .m_rip,
13281353 else => unreachable,
13291354 },
13301355 .data = .{ .x = .{
1356 .fixes = tag[0],
13311357 .payload = switch (m) {
13321358 .sib => try self.addExtra(Mir.MemorySib.encode(m)),
13331359 .rip => try self.addExtra(Mir.MemoryRip.encode(m)),
......@@ -1337,15 +1363,16 @@ fn asmMemory(self: *Self, tag: Mir.Inst.Tag, m: Memory) !void {
13371363 });
13381364}
13391365
1340fn asmRegisterMemory(self: *Self, tag: Mir.Inst.Tag, reg: Register, m: Memory) !void {
1366fn asmRegisterMemory(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, m: Memory) !void {
13411367 _ = try self.addInst(.{
1342 .tag = tag,
1368 .tag = tag[1],
13431369 .ops = switch (m) {
13441370 .sib => .rm_sib,
13451371 .rip => .rm_rip,
13461372 else => unreachable,
13471373 },
13481374 .data = .{ .rx = .{
1375 .fixes = tag[0],
13491376 .r1 = reg,
13501377 .payload = switch (m) {
13511378 .sib => try self.addExtra(Mir.MemorySib.encode(m)),
......@@ -1358,19 +1385,20 @@ fn asmRegisterMemory(self: *Self, tag: Mir.Inst.Tag, reg: Register, m: Memory) !
13581385
13591386fn asmRegisterMemoryImmediate(
13601387 self: *Self,
1361 tag: Mir.Inst.Tag,
1388 tag: Mir.Inst.FixedTag,
13621389 reg: Register,
13631390 m: Memory,
13641391 imm: Immediate,
13651392) !void {
13661393 _ = try self.addInst(.{
1367 .tag = tag,
1394 .tag = tag[1],
13681395 .ops = switch (m) {
13691396 .sib => .rmi_sib,
13701397 .rip => .rmi_rip,
13711398 else => unreachable,
13721399 },
13731400 .data = .{ .rix = .{
1401 .fixes = tag[0],
13741402 .r1 = reg,
13751403 .i = @intCast(u8, imm.unsigned),
13761404 .payload = switch (m) {
......@@ -1384,20 +1412,21 @@ fn asmRegisterMemoryImmediate(
13841412
13851413fn asmRegisterRegisterMemoryImmediate(
13861414 self: *Self,
1387 tag: Mir.Inst.Tag,
1415 tag: Mir.Inst.FixedTag,
13881416 reg1: Register,
13891417 reg2: Register,
13901418 m: Memory,
13911419 imm: Immediate,
13921420) !void {
13931421 _ = try self.addInst(.{
1394 .tag = tag,
1422 .tag = tag[1],
13951423 .ops = switch (m) {
13961424 .sib => .rrmi_sib,
13971425 .rip => .rrmi_rip,
13981426 else => unreachable,
13991427 },
14001428 .data = .{ .rrix = .{
1429 .fixes = tag[0],
14011430 .r1 = reg1,
14021431 .r2 = reg2,
14031432 .i = @intCast(u8, imm.unsigned),
......@@ -1410,15 +1439,16 @@ fn asmRegisterRegisterMemoryImmediate(
14101439 });
14111440}
14121441
1413fn asmMemoryRegister(self: *Self, tag: Mir.Inst.Tag, m: Memory, reg: Register) !void {
1442fn asmMemoryRegister(self: *Self, tag: Mir.Inst.FixedTag, m: Memory, reg: Register) !void {
14141443 _ = try self.addInst(.{
1415 .tag = tag,
1444 .tag = tag[1],
14161445 .ops = switch (m) {
14171446 .sib => .mr_sib,
14181447 .rip => .mr_rip,
14191448 else => unreachable,
14201449 },
14211450 .data = .{ .rx = .{
1451 .fixes = tag[0],
14221452 .r1 = reg,
14231453 .payload = switch (m) {
14241454 .sib => try self.addExtra(Mir.MemorySib.encode(m)),
......@@ -1429,9 +1459,9 @@ fn asmMemoryRegister(self: *Self, tag: Mir.Inst.Tag, m: Memory, reg: Register) !
14291459 });
14301460}
14311461
1432fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.Tag, m: Memory, imm: Immediate) !void {
1462fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.FixedTag, m: Memory, imm: Immediate) !void {
14331463 _ = try self.addInst(.{
1434 .tag = tag,
1464 .tag = tag[1],
14351465 .ops = switch (m) {
14361466 .sib => switch (imm) {
14371467 .signed => .mi_sib_s,
......@@ -1443,57 +1473,64 @@ fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.Tag, m: Memory, imm: Immediate)
14431473 },
14441474 else => unreachable,
14451475 },
1446 .data = .{ .ix = .{
1447 .i = switch (imm) {
1476 .data = .{ .x = .{
1477 .fixes = tag[0],
1478 .payload = try self.addExtra(Mir.Imm32{ .imm = switch (imm) {
14481479 .signed => |s| @bitCast(u32, s),
14491480 .unsigned => |u| @intCast(u32, u),
1450 },
1451 .payload = switch (m) {
1452 .sib => try self.addExtra(Mir.MemorySib.encode(m)),
1453 .rip => try self.addExtra(Mir.MemoryRip.encode(m)),
1454 else => unreachable,
1455 },
1481 } }),
14561482 } },
14571483 });
1484 _ = switch (m) {
1485 .sib => try self.addExtra(Mir.MemorySib.encode(m)),
1486 .rip => try self.addExtra(Mir.MemoryRip.encode(m)),
1487 else => unreachable,
1488 };
14581489}
14591490
14601491fn asmMemoryRegisterRegister(
14611492 self: *Self,
1462 tag: Mir.Inst.Tag,
1493 tag: Mir.Inst.FixedTag,
14631494 m: Memory,
14641495 reg1: Register,
14651496 reg2: Register,
14661497) !void {
14671498 _ = try self.addInst(.{
1468 .tag = tag,
1499 .tag = tag[1],
14691500 .ops = switch (m) {
14701501 .sib => .mrr_sib,
14711502 .rip => .mrr_rip,
14721503 else => unreachable,
14731504 },
1474 .data = .{ .rrx = .{ .r1 = reg1, .r2 = reg2, .payload = switch (m) {
1475 .sib => try self.addExtra(Mir.MemorySib.encode(m)),
1476 .rip => try self.addExtra(Mir.MemoryRip.encode(m)),
1477 else => unreachable,
1478 } } },
1505 .data = .{ .rrx = .{
1506 .fixes = tag[0],
1507 .r1 = reg1,
1508 .r2 = reg2,
1509 .payload = switch (m) {
1510 .sib => try self.addExtra(Mir.MemorySib.encode(m)),
1511 .rip => try self.addExtra(Mir.MemoryRip.encode(m)),
1512 else => unreachable,
1513 },
1514 } },
14791515 });
14801516}
14811517
14821518fn asmMemoryRegisterImmediate(
14831519 self: *Self,
1484 tag: Mir.Inst.Tag,
1520 tag: Mir.Inst.FixedTag,
14851521 m: Memory,
14861522 reg: Register,
14871523 imm: Immediate,
14881524) !void {
14891525 _ = try self.addInst(.{
1490 .tag = tag,
1526 .tag = tag[1],
14911527 .ops = switch (m) {
14921528 .sib => .mri_sib,
14931529 .rip => .mri_rip,
14941530 else => unreachable,
14951531 },
14961532 .data = .{ .rix = .{
1533 .fixes = tag[0],
14971534 .r1 = reg,
14981535 .i = @intCast(u8, imm.unsigned),
14991536 .payload = switch (m) {
......@@ -1508,9 +1545,9 @@ fn asmMemoryRegisterImmediate(
15081545fn gen(self: *Self) InnerError!void {
15091546 const cc = self.fn_type.fnCallingConvention();
15101547 if (cc != .Naked) {
1511 try self.asmRegister(.push, .rbp);
1548 try self.asmRegister(.{ ._, .push }, .rbp);
15121549 const backpatch_push_callee_preserved_regs = try self.asmPlaceholder();
1513 try self.asmRegisterRegister(.mov, .rbp, .rsp);
1550 try self.asmRegisterRegister(.{ ._, .mov }, .rbp, .rsp);
15141551 const backpatch_frame_align = try self.asmPlaceholder();
15151552 const backpatch_stack_alloc = try self.asmPlaceholder();
15161553
......@@ -1553,8 +1590,8 @@ fn gen(self: *Self) InnerError!void {
15531590 try self.asmPseudo(.pseudo_dbg_epilogue_begin_none);
15541591 const backpatch_stack_dealloc = try self.asmPlaceholder();
15551592 const backpatch_pop_callee_preserved_regs = try self.asmPlaceholder();
1556 try self.asmRegister(.pop, .rbp);
1557 try self.asmOpOnly(.ret);
1593 try self.asmRegister(.{ ._, .pop }, .rbp);
1594 try self.asmOpOnly(.{ ._, .ret });
15581595
15591596 const frame_layout = try self.computeFrameLayout();
15601597 const need_frame_align = frame_layout.stack_mask != math.maxInt(u32);
......@@ -1927,7 +1964,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
19271964 };
19281965 const tag_val = Value.initPayload(&tag_pl.base);
19291966 const tag_mcv = try self.genTypedValue(.{ .ty = enum_ty, .val = tag_val });
1930 try self.genBinOpMir(.cmp, enum_ty, enum_mcv, tag_mcv);
1967 try self.genBinOpMir(.{ ._, .cmp }, enum_ty, enum_mcv, tag_mcv);
19311968 const skip_reloc = try self.asmJccReloc(undefined, .ne);
19321969
19331970 try self.genSetMem(
......@@ -1947,7 +1984,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
19471984 try self.airTrap();
19481985
19491986 for (exitlude_jump_relocs) |reloc| try self.performReloc(reloc);
1950 try self.asmOpOnly(.ret);
1987 try self.asmOpOnly(.{ ._, .ret });
19511988 },
19521989 else => return self.fail(
19531990 "TODO implement {s} for {}",
......@@ -2406,7 +2443,7 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
24062443 else
24072444 try self.copyToTmpRegister(src_ty, src_mcv);
24082445 try self.asmRegisterRegisterImmediate(
2409 .vcvtps2ph,
2446 .{ ._, .vcvtps2ph },
24102447 dst_reg,
24112448 mat_src_reg.to128(),
24122449 Immediate.u(0b1_00),
......@@ -2418,12 +2455,12 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
24182455 }
24192456 } else if (src_bits == 64 and dst_bits == 32) {
24202457 if (self.hasFeature(.avx)) if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
2421 .vcvtsd2ss,
2458 .{ ._, .vcvtsd2ss },
24222459 dst_reg,
24232460 dst_reg,
24242461 src_mcv.mem(.qword),
24252462 ) else try self.asmRegisterRegisterRegister(
2426 .vcvtsd2ss,
2463 .{ ._, .vcvtsd2ss },
24272464 dst_reg,
24282465 dst_reg,
24292466 (if (src_mcv.isRegister())
......@@ -2431,11 +2468,11 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
24312468 else
24322469 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
24332470 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
2434 .cvtsd2ss,
2471 .{ ._, .cvtsd2ss },
24352472 dst_reg,
24362473 src_mcv.mem(.qword),
24372474 ) else try self.asmRegisterRegister(
2438 .cvtsd2ss,
2475 .{ ._, .cvtsd2ss },
24392476 dst_reg,
24402477 (if (src_mcv.isRegister())
24412478 src_mcv.getReg().?
......@@ -2469,22 +2506,22 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
24692506 src_mcv.getReg().?
24702507 else
24712508 try self.copyToTmpRegister(src_ty, src_mcv);
2472 try self.asmRegisterRegister(.vcvtph2ps, dst_reg, mat_src_reg.to128());
2509 try self.asmRegisterRegister(.{ ._, .vcvtph2ps }, dst_reg, mat_src_reg.to128());
24732510 switch (dst_bits) {
24742511 32 => {},
2475 64 => try self.asmRegisterRegisterRegister(.vcvtss2sd, dst_reg, dst_reg, dst_reg),
2512 64 => try self.asmRegisterRegisterRegister(.{ ._, .vcvtss2sd }, dst_reg, dst_reg, dst_reg),
24762513 else => return self.fail("TODO implement airFpext from {} to {}", .{
24772514 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
24782515 }),
24792516 }
24802517 } else if (src_bits == 32 and dst_bits == 64) {
24812518 if (self.hasFeature(.avx)) if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
2482 .vcvtss2sd,
2519 .{ ._, .vcvtss2sd },
24832520 dst_reg,
24842521 dst_reg,
24852522 src_mcv.mem(.dword),
24862523 ) else try self.asmRegisterRegisterRegister(
2487 .vcvtss2sd,
2524 .{ ._, .vcvtss2sd },
24882525 dst_reg,
24892526 dst_reg,
24902527 (if (src_mcv.isRegister())
......@@ -2492,11 +2529,11 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
24922529 else
24932530 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
24942531 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
2495 .cvtss2sd,
2532 .{ ._, .cvtss2sd },
24962533 dst_reg,
24972534 src_mcv.mem(.dword),
24982535 ) else try self.asmRegisterRegister(
2499 .cvtss2sd,
2536 .{ ._, .cvtss2sd },
25002537 dst_reg,
25012538 (if (src_mcv.isRegister())
25022539 src_mcv.getReg().?
......@@ -2537,12 +2574,12 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
25372574 switch (dst_mcv) {
25382575 .register => |dst_reg| {
25392576 const min_abi_size = @min(dst_abi_size, src_abi_size);
2540 const tag: Mir.Inst.Tag = switch (signedness) {
2541 .signed => if (min_abi_size >= 4) .movsxd else .movsx,
2542 .unsigned => if (min_abi_size >= 4) .mov else .movzx,
2577 const tag: Mir.Inst.FixedTag = switch (signedness) {
2578 .signed => if (min_abi_size >= 4) .{ ._d, .movsx } else .{ ._, .movsx },
2579 .unsigned => if (min_abi_size >= 4) .{ ._, .mov } else .{ ._, .movzx },
25432580 };
2544 const dst_alias = switch (tag) {
2545 .movsx, .movsxd => dst_reg.to64(),
2581 const dst_alias = switch (tag[1]) {
2582 .movsx => dst_reg.to64(),
25462583 .mov, .movzx => if (min_abi_size > 4) dst_reg.to64() else dst_reg.to32(),
25472584 else => unreachable,
25482585 };
......@@ -2570,14 +2607,24 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
25702607 try self.genCopy(min_ty, dst_mcv, src_mcv);
25712608 const extra = dst_abi_size * 8 - dst_int_info.bits;
25722609 if (extra > 0) {
2573 try self.genShiftBinOpMir(switch (signedness) {
2574 .signed => .sal,
2575 .unsigned => .shl,
2576 }, dst_ty, dst_mcv, .{ .immediate = extra });
2577 try self.genShiftBinOpMir(switch (signedness) {
2578 .signed => .sar,
2579 .unsigned => .shr,
2580 }, dst_ty, dst_mcv, .{ .immediate = extra });
2610 try self.genShiftBinOpMir(
2611 switch (signedness) {
2612 .signed => .{ ._l, .sa },
2613 .unsigned => .{ ._l, .sh },
2614 },
2615 dst_ty,
2616 dst_mcv,
2617 .{ .immediate = extra },
2618 );
2619 try self.genShiftBinOpMir(
2620 switch (signedness) {
2621 .signed => .{ ._r, .sa },
2622 .unsigned => .{ ._r, .sh },
2623 },
2624 dst_ty,
2625 dst_mcv,
2626 .{ .immediate = extra },
2627 );
25812628 }
25822629 },
25832630 }
......@@ -2762,8 +2809,8 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
27622809 const reg_bits = self.regBitSize(ty);
27632810 const cc: Condition = if (ty.isSignedInt()) cc: {
27642811 try self.genSetReg(limit_reg, ty, dst_mcv);
2765 try self.genShiftBinOpMir(.sar, ty, limit_mcv, .{ .immediate = reg_bits - 1 });
2766 try self.genBinOpMir(.xor, ty, limit_mcv, .{
2812 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 });
2813 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{
27672814 .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1,
27682815 });
27692816 break :cc .o;
......@@ -2773,7 +2820,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
27732820 });
27742821 break :cc .c;
27752822 };
2776 try self.genBinOpMir(.add, ty, dst_mcv, rhs_mcv);
2823 try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv);
27772824
27782825 const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2);
27792826 try self.asmCmovccRegisterRegister(
......@@ -2813,8 +2860,8 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
28132860 const reg_bits = self.regBitSize(ty);
28142861 const cc: Condition = if (ty.isSignedInt()) cc: {
28152862 try self.genSetReg(limit_reg, ty, dst_mcv);
2816 try self.genShiftBinOpMir(.sar, ty, limit_mcv, .{ .immediate = reg_bits - 1 });
2817 try self.genBinOpMir(.xor, ty, limit_mcv, .{
2863 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 });
2864 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{
28182865 .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1,
28192866 });
28202867 break :cc .o;
......@@ -2822,7 +2869,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
28222869 try self.genSetReg(limit_reg, ty, .{ .immediate = 0 });
28232870 break :cc .c;
28242871 };
2825 try self.genBinOpMir(.sub, ty, dst_mcv, rhs_mcv);
2872 try self.genBinOpMir(.{ ._, .sub }, ty, dst_mcv, rhs_mcv);
28262873
28272874 const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2);
28282875 try self.asmCmovccRegisterRegister(
......@@ -2864,9 +2911,9 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
28642911 const reg_bits = self.regBitSize(ty);
28652912 const cc: Condition = if (ty.isSignedInt()) cc: {
28662913 try self.genSetReg(limit_reg, ty, lhs_mcv);
2867 try self.genBinOpMir(.xor, ty, limit_mcv, rhs_mcv);
2868 try self.genShiftBinOpMir(.sar, ty, limit_mcv, .{ .immediate = reg_bits - 1 });
2869 try self.genBinOpMir(.xor, ty, limit_mcv, .{
2914 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, rhs_mcv);
2915 try self.genShiftBinOpMir(.{ ._, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 });
2916 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{
28702917 .immediate = (@as(u64, 1) << @intCast(u6, reg_bits - 1)) - 1,
28712918 });
28722919 break :cc .o;
......@@ -2979,7 +3026,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
29793026 };
29803027 defer if (tmp_lock) |lock| self.register_manager.unlockReg(lock);
29813028
2982 try self.genBinOpMir(.cmp, lhs_ty, tmp_mcv, lhs);
3029 try self.genBinOpMir(.{ ._, .cmp }, lhs_ty, tmp_mcv, lhs);
29833030 const cc = Condition.ne;
29843031
29853032 const tuple_ty = self.air.typeOfIndex(inst);
......@@ -3066,12 +3113,17 @@ fn genSetFrameTruncatedOverflowCompare(
30663113 src_mcv;
30673114 try self.genSetReg(scratch_reg, hi_limb_ty, hi_limb_mcv);
30683115 try self.truncateRegister(hi_limb_ty, scratch_reg);
3069 try self.genBinOpMir(.cmp, hi_limb_ty, .{ .register = scratch_reg }, hi_limb_mcv);
3116 try self.genBinOpMir(.{ ._, .cmp }, hi_limb_ty, .{ .register = scratch_reg }, hi_limb_mcv);
30703117
30713118 const eq_reg = temp_regs[2];
30723119 if (overflow_cc) |_| {
30733120 try self.asmSetccRegister(eq_reg.to8(), .ne);
3074 try self.genBinOpMir(.@"or", Type.u8, .{ .register = overflow_reg }, .{ .register = eq_reg });
3121 try self.genBinOpMir(
3122 .{ ._, .@"or" },
3123 Type.u8,
3124 .{ .register = overflow_reg },
3125 .{ .register = eq_reg },
3126 );
30753127 }
30763128
30773129 const payload_off = @intCast(i32, tuple_ty.structFieldOffset(0, self.target.*));
......@@ -3200,28 +3252,25 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
32003252/// Generates signed or unsigned integer multiplication/division.
32013253/// Clobbers .rax and .rdx registers.
32023254/// Quotient is saved in .rax and remainder in .rdx.
3203fn genIntMulDivOpMir(
3204 self: *Self,
3205 tag: Mir.Inst.Tag,
3206 ty: Type,
3207 lhs: MCValue,
3208 rhs: MCValue,
3209) !void {
3255fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue, rhs: MCValue) !void {
32103256 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
32113257 if (abi_size > 8) {
32123258 return self.fail("TODO implement genIntMulDivOpMir for ABI size larger than 8", .{});
32133259 }
32143260
32153261 try self.genSetReg(.rax, ty, lhs);
3216 switch (tag) {
3262 switch (tag[1]) {
32173263 else => unreachable,
3218 .mul, .imul => {},
3219 .div => try self.asmRegisterRegister(.xor, .edx, .edx),
3220 .idiv => switch (self.regBitSize(ty)) {
3221 8 => try self.asmOpOnly(.cbw),
3222 16 => try self.asmOpOnly(.cwd),
3223 32 => try self.asmOpOnly(.cdq),
3224 64 => try self.asmOpOnly(.cqo),
3264 .mul => {},
3265 .div => switch (tag[0]) {
3266 ._ => try self.asmRegisterRegister(.{ ._, .xor }, .edx, .edx),
3267 .i_ => switch (self.regBitSize(ty)) {
3268 8 => try self.asmOpOnly(.{ ._, .cbw }),
3269 16 => try self.asmOpOnly(.{ ._, .cwd }),
3270 32 => try self.asmOpOnly(.{ ._, .cdq }),
3271 64 => try self.asmOpOnly(.{ ._, .cqo }),
3272 else => unreachable,
3273 },
32253274 else => unreachable,
32263275 },
32273276 }
......@@ -3259,23 +3308,28 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa
32593308 const divisor_lock = self.register_manager.lockReg(divisor);
32603309 defer if (divisor_lock) |lock| self.register_manager.unlockReg(lock);
32613310
3262 try self.genIntMulDivOpMir(switch (int_info.signedness) {
3263 .signed => .idiv,
3264 .unsigned => .div,
3265 }, ty, .{ .register = dividend }, .{ .register = divisor });
3311 try self.genIntMulDivOpMir(
3312 switch (int_info.signedness) {
3313 .signed => .{ .i_, .div },
3314 .unsigned => .{ ._, .div },
3315 },
3316 ty,
3317 .{ .register = dividend },
3318 .{ .register = divisor },
3319 );
32663320
32673321 try self.asmRegisterRegister(
3268 .xor,
3322 .{ ._, .xor },
32693323 registerAlias(divisor, abi_size),
32703324 registerAlias(dividend, abi_size),
32713325 );
32723326 try self.asmRegisterImmediate(
3273 .sar,
3327 .{ ._r, .sa },
32743328 registerAlias(divisor, abi_size),
32753329 Immediate.u(int_info.bits - 1),
32763330 );
32773331 try self.asmRegisterRegister(
3278 .@"test",
3332 .{ ._, .@"test" },
32793333 registerAlias(.rdx, abi_size),
32803334 registerAlias(.rdx, abi_size),
32813335 );
......@@ -3284,7 +3338,7 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa
32843338 registerAlias(.rdx, abi_size),
32853339 .z,
32863340 );
3287 try self.genBinOpMir(.add, ty, .{ .register = divisor }, .{ .register = .rax });
3341 try self.genBinOpMir(.{ ._, .add }, ty, .{ .register = divisor }, .{ .register = .rax });
32883342 return MCValue{ .register = divisor };
32893343}
32903344
......@@ -3406,7 +3460,12 @@ fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
34063460 const result = try self.copyToRegisterWithInstTracking(inst, err_union_ty, operand);
34073461 if (err_off > 0) {
34083462 const shift = @intCast(u6, err_off * 8);
3409 try self.genShiftBinOpMir(.shr, err_union_ty, result, .{ .immediate = shift });
3463 try self.genShiftBinOpMir(
3464 .{ ._r, .sh },
3465 err_union_ty,
3466 result,
3467 .{ .immediate = shift },
3468 );
34103469 } else {
34113470 try self.truncateRegister(Type.anyerror, result.register);
34123471 }
......@@ -3458,7 +3517,12 @@ fn genUnwrapErrorUnionPayloadMir(
34583517 .{ .register = try self.copyToTmpRegister(err_union_ty, err_union) };
34593518 if (payload_off > 0) {
34603519 const shift = @intCast(u6, payload_off * 8);
3461 try self.genShiftBinOpMir(.shr, err_union_ty, result_mcv, .{ .immediate = shift });
3520 try self.genShiftBinOpMir(
3521 .{ ._r, .sh },
3522 err_union_ty,
3523 result_mcv,
3524 .{ .immediate = shift },
3525 );
34623526 } else {
34633527 try self.truncateRegister(payload_ty, result_mcv.register);
34643528 }
......@@ -3495,7 +3559,7 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {
34953559 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*));
34963560 const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*));
34973561 try self.asmRegisterMemory(
3498 .mov,
3562 .{ ._, .mov },
34993563 registerAlias(dst_reg, err_abi_size),
35003564 Memory.sib(Memory.PtrSize.fromSize(err_abi_size), .{
35013565 .base = .{ .reg = src_reg },
......@@ -3533,7 +3597,7 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
35333597 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, self.target.*));
35343598 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
35353599 try self.asmRegisterMemory(
3536 .lea,
3600 .{ ._, .lea },
35373601 registerAlias(dst_reg, dst_abi_size),
35383602 Memory.sib(.qword, .{ .base = .{ .reg = src_reg }, .disp = pl_off }),
35393603 );
......@@ -3559,7 +3623,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
35593623 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*));
35603624 const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*));
35613625 try self.asmMemoryImmediate(
3562 .mov,
3626 .{ ._, .mov },
35633627 Memory.sib(Memory.PtrSize.fromSize(err_abi_size), .{
35643628 .base = .{ .reg = src_reg },
35653629 .disp = err_off,
......@@ -3580,7 +3644,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
35803644 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, self.target.*));
35813645 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
35823646 try self.asmRegisterMemory(
3583 .lea,
3647 .{ ._, .lea },
35843648 registerAlias(dst_reg, dst_abi_size),
35853649 Memory.sib(.qword, .{ .base = .{ .reg = src_reg }, .disp = pl_off }),
35863650 );
......@@ -3631,13 +3695,13 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
36313695 else => unreachable,
36323696
36333697 .register => |opt_reg| try self.asmRegisterImmediate(
3634 .bts,
3698 .{ ._s, .bt },
36353699 opt_reg,
36363700 Immediate.u(@intCast(u6, pl_abi_size * 8)),
36373701 ),
36383702
36393703 .load_frame => |frame_addr| try self.asmMemoryImmediate(
3640 .mov,
3704 .{ ._, .mov },
36413705 Memory.sib(.byte, .{
36423706 .base = .{ .frame = frame_addr.index },
36433707 .disp = frame_addr.off + pl_abi_size,
......@@ -3749,7 +3813,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {
37493813
37503814 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
37513815 try self.asmRegisterMemory(
3752 .lea,
3816 .{ ._, .lea },
37533817 registerAlias(dst_reg, dst_abi_size),
37543818 Memory.sib(.qword, .{
37553819 .base = .{ .reg = src_reg },
......@@ -3823,7 +3887,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
38233887 try self.genSetReg(addr_reg, Type.usize, slice_mcv);
38243888 // TODO we could allocate register here, but need to expect addr register and potentially
38253889 // offset register.
3826 try self.genBinOpMir(.add, slice_ptr_field_type, .{ .register = addr_reg }, .{
3890 try self.genBinOpMir(.{ ._, .add }, slice_ptr_field_type, .{ .register = addr_reg }, .{
38273891 .register = offset_reg,
38283892 });
38293893 return MCValue{ .register = addr_reg.to64() };
......@@ -3881,13 +3945,13 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
38813945 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(array_ty, self.target.*));
38823946 try self.genSetMem(.{ .frame = frame_index }, 0, array_ty, array);
38833947 try self.asmRegisterMemory(
3884 .lea,
3948 .{ ._, .lea },
38853949 addr_reg,
38863950 Memory.sib(.qword, .{ .base = .{ .frame = frame_index } }),
38873951 );
38883952 },
38893953 .load_frame => |frame_addr| try self.asmRegisterMemory(
3890 .lea,
3954 .{ ._, .lea },
38913955 addr_reg,
38923956 Memory.sib(.qword, .{ .base = .{ .frame = frame_addr.index }, .disp = frame_addr.off }),
38933957 ),
......@@ -3903,7 +3967,12 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
39033967 // TODO we could allocate register here, but need to expect addr register and potentially
39043968 // offset register.
39053969 const dst_mcv = try self.allocRegOrMem(inst, false);
3906 try self.genBinOpMir(.add, Type.usize, .{ .register = addr_reg }, .{ .register = offset_reg });
3970 try self.genBinOpMir(
3971 .{ ._, .add },
3972 Type.usize,
3973 .{ .register = addr_reg },
3974 .{ .register = offset_reg },
3975 );
39073976 try self.genCopy(elem_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } });
39083977
39093978 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
......@@ -3937,7 +4006,11 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
39374006 try self.copyToTmpRegister(ptr_ty, ptr_mcv);
39384007 const elem_ptr_lock = self.register_manager.lockRegAssumeUnused(elem_ptr_reg);
39394008 defer self.register_manager.unlockReg(elem_ptr_lock);
3940 try self.asmRegisterRegister(.add, elem_ptr_reg, offset_reg);
4009 try self.asmRegisterRegister(
4010 .{ ._, .add },
4011 elem_ptr_reg,
4012 offset_reg,
4013 );
39414014
39424015 const dst_mcv = try self.allocRegOrMem(inst, true);
39434016 const dst_lock = switch (dst_mcv) {
......@@ -3977,7 +4050,7 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
39774050 defer self.register_manager.unlockReg(offset_reg_lock);
39784051
39794052 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr);
3980 try self.genBinOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });
4053 try self.genBinOpMir(.{ ._, .add }, ptr_ty, dst_mcv, .{ .register = offset_reg });
39814054
39824055 return self.finishAir(inst, dst_mcv, .{ extra.lhs, extra.rhs, .none });
39834056}
......@@ -4010,7 +4083,12 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
40104083 const adjusted_ptr: MCValue = if (layout.payload_size > 0 and layout.tag_align < layout.payload_align) blk: {
40114084 // TODO reusing the operand
40124085 const reg = try self.copyToTmpRegister(ptr_union_ty, ptr);
4013 try self.genBinOpMir(.add, ptr_union_ty, .{ .register = reg }, .{ .immediate = layout.payload_size });
4086 try self.genBinOpMir(
4087 .{ ._, .add },
4088 ptr_union_ty,
4089 .{ .register = reg },
4090 .{ .immediate = layout.payload_size },
4091 );
40144092 break :blk MCValue{ .register = reg };
40154093 } else ptr;
40164094
......@@ -4063,7 +4141,7 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
40634141 else
40644142 0;
40654143 const result = try self.copyToRegisterWithInstTracking(inst, union_ty, operand);
4066 try self.genShiftBinOpMir(.shr, Type.usize, result, .{ .immediate = shift });
4144 try self.genShiftBinOpMir(.{ ._r, .sh }, Type.usize, result, .{ .immediate = shift });
40674145 break :blk MCValue{
40684146 .register = registerAlias(result.register, @intCast(u32, layout.tag_size)),
40694147 };
......@@ -4100,11 +4178,11 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
41004178 const src_bits = src_ty.bitSize(self.target.*);
41014179 if (self.hasFeature(.lzcnt)) {
41024180 if (src_bits <= 64) {
4103 try self.genBinOpMir(.lzcnt, src_ty, dst_mcv, mat_src_mcv);
4181 try self.genBinOpMir(.{ ._, .lzcnt }, src_ty, dst_mcv, mat_src_mcv);
41044182
41054183 const extra_bits = self.regExtraBits(src_ty);
41064184 if (extra_bits > 0) {
4107 try self.genBinOpMir(.sub, dst_ty, dst_mcv, .{ .immediate = extra_bits });
4185 try self.genBinOpMir(.{ ._, .sub }, dst_ty, dst_mcv, .{ .immediate = extra_bits });
41084186 }
41094187 } else if (src_bits <= 128) {
41104188 const tmp_reg = try self.register_manager.allocReg(null, gp);
......@@ -4112,13 +4190,23 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
41124190 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
41134191 defer self.register_manager.unlockReg(tmp_lock);
41144192
4115 try self.genBinOpMir(.lzcnt, Type.u64, dst_mcv, mat_src_mcv);
4116 try self.genBinOpMir(.add, dst_ty, dst_mcv, .{ .immediate = 64 });
4117 try self.genBinOpMir(.lzcnt, Type.u64, tmp_mcv, mat_src_mcv.address().offset(8).deref());
4193 try self.genBinOpMir(.{ ._, .lzcnt }, Type.u64, dst_mcv, mat_src_mcv);
4194 try self.genBinOpMir(.{ ._, .add }, dst_ty, dst_mcv, .{ .immediate = 64 });
4195 try self.genBinOpMir(
4196 .{ ._, .lzcnt },
4197 Type.u64,
4198 tmp_mcv,
4199 mat_src_mcv.address().offset(8).deref(),
4200 );
41184201 try self.asmCmovccRegisterRegister(dst_reg.to32(), tmp_reg.to32(), .nc);
41194202
41204203 if (src_bits < 128) {
4121 try self.genBinOpMir(.sub, dst_ty, dst_mcv, .{ .immediate = 128 - src_bits });
4204 try self.genBinOpMir(
4205 .{ ._, .sub },
4206 dst_ty,
4207 dst_mcv,
4208 .{ .immediate = 128 - src_bits },
4209 );
41224210 }
41234211 } else return self.fail("TODO airClz of {}", .{src_ty.fmt(self.bin_file.options.module.?)});
41244212 break :result dst_mcv;
......@@ -4130,7 +4218,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
41304218 const imm_reg = try self.copyToTmpRegister(dst_ty, .{
41314219 .immediate = src_bits ^ (src_bits - 1),
41324220 });
4133 try self.genBinOpMir(.bsr, src_ty, dst_mcv, mat_src_mcv);
4221 try self.genBinOpMir(.{ ._, .bsr }, src_ty, dst_mcv, mat_src_mcv);
41344222
41354223 const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2);
41364224 try self.asmCmovccRegisterRegister(
......@@ -4139,12 +4227,12 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
41394227 .z,
41404228 );
41414229
4142 try self.genBinOpMir(.xor, dst_ty, dst_mcv, .{ .immediate = src_bits - 1 });
4230 try self.genBinOpMir(.{ ._, .xor }, dst_ty, dst_mcv, .{ .immediate = src_bits - 1 });
41434231 } else {
41444232 const imm_reg = try self.copyToTmpRegister(dst_ty, .{
41454233 .immediate = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - self.regBitSize(dst_ty)),
41464234 });
4147 try self.genBinOpMir(.bsr, src_ty, dst_mcv, mat_src_mcv);
4235 try self.genBinOpMir(.{ ._, .bsr }, src_ty, dst_mcv, mat_src_mcv);
41484236
41494237 const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2);
41504238 try self.asmCmovccRegisterRegister(
......@@ -4154,7 +4242,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
41544242 );
41554243
41564244 try self.genSetReg(dst_reg, dst_ty, .{ .immediate = src_bits - 1 });
4157 try self.genBinOpMir(.sub, dst_ty, dst_mcv, .{ .register = imm_reg });
4245 try self.genBinOpMir(.{ ._, .sub }, dst_ty, dst_mcv, .{ .register = imm_reg });
41584246 }
41594247 break :result dst_mcv;
41604248 };
......@@ -4195,7 +4283,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
41954283 break :tmp dst_mcv;
41964284 };
41974285 try self.genBinOpMir(
4198 .@"or",
4286 .{ ._, .@"or" },
41994287 src_ty,
42004288 tmp_mcv,
42014289 .{ .immediate = (@as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - extra_bits)) <<
......@@ -4203,7 +4291,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
42034291 );
42044292 break :masked tmp_mcv;
42054293 } else mat_src_mcv;
4206 try self.genBinOpMir(.tzcnt, src_ty, dst_mcv, masked_mcv);
4294 try self.genBinOpMir(.{ ._, .tzcnt }, src_ty, dst_mcv, masked_mcv);
42074295 } else if (src_bits <= 128) {
42084296 const tmp_reg = try self.register_manager.allocReg(null, gp);
42094297 const tmp_mcv = MCValue{ .register = tmp_reg };
......@@ -4213,16 +4301,16 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
42134301 const masked_mcv = if (src_bits < 128) masked: {
42144302 try self.genCopy(Type.u64, dst_mcv, mat_src_mcv.address().offset(8).deref());
42154303 try self.genBinOpMir(
4216 .@"or",
4304 .{ ._, .@"or" },
42174305 Type.u64,
42184306 dst_mcv,
42194307 .{ .immediate = @as(u64, math.maxInt(u64)) << @intCast(u6, src_bits - 64) },
42204308 );
42214309 break :masked dst_mcv;
42224310 } else mat_src_mcv.address().offset(8).deref();
4223 try self.genBinOpMir(.tzcnt, Type.u64, dst_mcv, masked_mcv);
4224 try self.genBinOpMir(.add, dst_ty, dst_mcv, .{ .immediate = 64 });
4225 try self.genBinOpMir(.tzcnt, Type.u64, tmp_mcv, mat_src_mcv);
4311 try self.genBinOpMir(.{ ._, .tzcnt }, Type.u64, dst_mcv, masked_mcv);
4312 try self.genBinOpMir(.{ ._, .add }, dst_ty, dst_mcv, .{ .immediate = 64 });
4313 try self.genBinOpMir(.{ ._, .tzcnt }, Type.u64, tmp_mcv, mat_src_mcv);
42264314 try self.asmCmovccRegisterRegister(dst_reg.to32(), tmp_reg.to32(), .nc);
42274315 } else return self.fail("TODO airCtz of {}", .{src_ty.fmt(self.bin_file.options.module.?)});
42284316 break :result dst_mcv;
......@@ -4232,7 +4320,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
42324320 return self.fail("TODO airCtz of {}", .{src_ty.fmt(self.bin_file.options.module.?)});
42334321
42344322 const width_reg = try self.copyToTmpRegister(dst_ty, .{ .immediate = src_bits });
4235 try self.genBinOpMir(.bsf, src_ty, dst_mcv, mat_src_mcv);
4323 try self.genBinOpMir(.{ ._, .bsf }, src_ty, dst_mcv, mat_src_mcv);
42364324
42374325 const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2);
42384326 try self.asmCmovccRegisterRegister(
......@@ -4270,7 +4358,7 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
42704358 .{ .register = try self.register_manager.allocReg(inst, gp) };
42714359
42724360 const popcnt_ty = if (src_abi_size > 1) src_ty else Type.u16;
4273 try self.genBinOpMir(.popcnt, popcnt_ty, dst_mcv, mat_src_mcv);
4361 try self.genBinOpMir(.{ ._, .popcnt }, popcnt_ty, dst_mcv, mat_src_mcv);
42744362 break :result dst_mcv;
42754363 }
42764364
......@@ -4301,54 +4389,54 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
43014389 undefined;
43024390
43034391 // dst = operand
4304 try self.asmRegisterRegister(.mov, tmp, dst);
4392 try self.asmRegisterRegister(.{ ._, .mov }, tmp, dst);
43054393 // tmp = operand
4306 try self.asmRegisterImmediate(.shr, tmp, Immediate.u(1));
4394 try self.asmRegisterImmediate(.{ ._r, .sh }, tmp, Immediate.u(1));
43074395 // tmp = operand >> 1
43084396 if (src_abi_size > 4) {
4309 try self.asmRegisterImmediate(.mov, imm, imm_0_1);
4310 try self.asmRegisterRegister(.@"and", tmp, imm);
4311 } else try self.asmRegisterImmediate(.@"and", tmp, imm_0_1);
4397 try self.asmRegisterImmediate(.{ ._, .mov }, imm, imm_0_1);
4398 try self.asmRegisterRegister(.{ ._, .@"and" }, tmp, imm);
4399 } else try self.asmRegisterImmediate(.{ ._, .@"and" }, tmp, imm_0_1);
43124400 // tmp = (operand >> 1) & 0x55...55
4313 try self.asmRegisterRegister(.sub, dst, tmp);
4401 try self.asmRegisterRegister(.{ ._, .sub }, dst, tmp);
43144402 // dst = temp1 = operand - ((operand >> 1) & 0x55...55)
4315 try self.asmRegisterRegister(.mov, tmp, dst);
4403 try self.asmRegisterRegister(.{ ._, .mov }, tmp, dst);
43164404 // tmp = temp1
4317 try self.asmRegisterImmediate(.shr, dst, Immediate.u(2));
4405 try self.asmRegisterImmediate(.{ ._r, .sh }, dst, Immediate.u(2));
43184406 // dst = temp1 >> 2
43194407 if (src_abi_size > 4) {
4320 try self.asmRegisterImmediate(.mov, imm, imm_00_11);
4321 try self.asmRegisterRegister(.@"and", tmp, imm);
4322 try self.asmRegisterRegister(.@"and", dst, imm);
4408 try self.asmRegisterImmediate(.{ ._, .mov }, imm, imm_00_11);
4409 try self.asmRegisterRegister(.{ ._, .@"and" }, tmp, imm);
4410 try self.asmRegisterRegister(.{ ._, .@"and" }, dst, imm);
43234411 } else {
4324 try self.asmRegisterImmediate(.@"and", tmp, imm_00_11);
4325 try self.asmRegisterImmediate(.@"and", dst, imm_00_11);
4412 try self.asmRegisterImmediate(.{ ._, .@"and" }, tmp, imm_00_11);
4413 try self.asmRegisterImmediate(.{ ._, .@"and" }, dst, imm_00_11);
43264414 }
43274415 // tmp = temp1 & 0x33...33
43284416 // dst = (temp1 >> 2) & 0x33...33
4329 try self.asmRegisterRegister(.add, tmp, dst);
4417 try self.asmRegisterRegister(.{ ._, .add }, tmp, dst);
43304418 // tmp = temp2 = (temp1 & 0x33...33) + ((temp1 >> 2) & 0x33...33)
4331 try self.asmRegisterRegister(.mov, dst, tmp);
4419 try self.asmRegisterRegister(.{ ._, .mov }, dst, tmp);
43324420 // dst = temp2
4333 try self.asmRegisterImmediate(.shr, tmp, Immediate.u(4));
4421 try self.asmRegisterImmediate(.{ ._r, .sh }, tmp, Immediate.u(4));
43344422 // tmp = temp2 >> 4
4335 try self.asmRegisterRegister(.add, dst, tmp);
4423 try self.asmRegisterRegister(.{ ._, .add }, dst, tmp);
43364424 // dst = temp2 + (temp2 >> 4)
43374425 if (src_abi_size > 4) {
4338 try self.asmRegisterImmediate(.mov, imm, imm_0000_1111);
4339 try self.asmRegisterImmediate(.mov, tmp, imm_0000_0001);
4340 try self.asmRegisterRegister(.@"and", dst, imm);
4341 try self.asmRegisterRegister(.imul, dst, tmp);
4426 try self.asmRegisterImmediate(.{ ._, .mov }, imm, imm_0000_1111);
4427 try self.asmRegisterImmediate(.{ ._, .mov }, tmp, imm_0000_0001);
4428 try self.asmRegisterRegister(.{ ._, .@"and" }, dst, imm);
4429 try self.asmRegisterRegister(.{ .i_, .mul }, dst, tmp);
43424430 } else {
4343 try self.asmRegisterImmediate(.@"and", dst, imm_0000_1111);
4431 try self.asmRegisterImmediate(.{ ._, .@"and" }, dst, imm_0000_1111);
43444432 if (src_abi_size > 1) {
4345 try self.asmRegisterRegisterImmediate(.imul, dst, dst, imm_0000_0001);
4433 try self.asmRegisterRegisterImmediate(.{ .i_, .mul }, dst, dst, imm_0000_0001);
43464434 }
43474435 }
43484436 // dst = temp3 = (temp2 + (temp2 >> 4)) & 0x0f...0f
43494437 // dst = temp3 * 0x01...01
43504438 if (src_abi_size > 1) {
4351 try self.asmRegisterImmediate(.shr, dst, Immediate.u((src_abi_size - 1) * 8));
4439 try self.asmRegisterImmediate(.{ ._r, .sh }, dst, Immediate.u((src_abi_size - 1) * 8));
43524440 }
43534441 // dst = (temp3 * 0x01...01) >> (bits - 8)
43544442 }
......@@ -4377,11 +4465,11 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m
43774465 16 => if ((mem_ok or src_mcv.isRegister()) and
43784466 self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
43794467 {
4380 try self.genBinOpMir(.rol, src_ty, src_mcv, .{ .immediate = 8 });
4468 try self.genBinOpMir(.{ ._l, .ro }, src_ty, src_mcv, .{ .immediate = 8 });
43814469 return src_mcv;
43824470 },
43834471 32, 64 => if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) {
4384 try self.genUnOpMir(.bswap, src_ty, src_mcv);
4472 try self.genUnOpMir(.{ ._, .bswap }, src_ty, src_mcv);
43854473 return src_mcv;
43864474 },
43874475 }
......@@ -4398,10 +4486,10 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m
43984486 try self.genSetReg(dst_mcv.register, src_ty, src_mcv);
43994487 switch (src_bits) {
44004488 else => unreachable,
4401 16 => try self.genBinOpMir(.rol, src_ty, dst_mcv, .{ .immediate = 8 }),
4402 32, 64 => try self.genUnOpMir(.bswap, src_ty, dst_mcv),
4489 16 => try self.genBinOpMir(.{ ._l, .ro }, src_ty, dst_mcv, .{ .immediate = 8 }),
4490 32, 64 => try self.genUnOpMir(.{ ._, .bswap }, src_ty, dst_mcv),
44034491 }
4404 } else try self.genBinOpMir(.movbe, src_ty, dst_mcv, src_mcv);
4492 } else try self.genBinOpMir(.{ ._, .movbe }, src_ty, dst_mcv, src_mcv);
44054493 return dst_mcv;
44064494 }
44074495
......@@ -4410,7 +4498,7 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m
44104498 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
44114499 defer self.register_manager.unlockReg(dst_lock);
44124500
4413 try self.genBinOpMir(.movbe, src_ty, dst_mcv, src_mcv);
4501 try self.genBinOpMir(.{ ._, .movbe }, src_ty, dst_mcv, src_mcv);
44144502 return dst_mcv;
44154503}
44164504
......@@ -4424,7 +4512,7 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
44244512 switch (self.regExtraBits(src_ty)) {
44254513 0 => {},
44264514 else => |extra| try self.genBinOpMir(
4427 if (src_ty.isSignedInt()) .sar else .shr,
4515 if (src_ty.isSignedInt()) .{ ._r, .sa } else .{ ._r, .sh },
44284516 src_ty,
44294517 dst_mcv,
44304518 .{ .immediate = extra },
......@@ -4464,40 +4552,40 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
44644552 const imm_0_1 = Immediate.u(mask / 0b1_1);
44654553
44664554 // dst = temp1 = bswap(operand)
4467 try self.asmRegisterRegister(.mov, tmp, dst);
4555 try self.asmRegisterRegister(.{ ._, .mov }, tmp, dst);
44684556 // tmp = temp1
4469 try self.asmRegisterImmediate(.shr, dst, Immediate.u(4));
4557 try self.asmRegisterImmediate(.{ ._r, .sh }, dst, Immediate.u(4));
44704558 // dst = temp1 >> 4
44714559 if (src_abi_size > 4) {
4472 try self.asmRegisterImmediate(.mov, imm, imm_0000_1111);
4473 try self.asmRegisterRegister(.@"and", tmp, imm);
4474 try self.asmRegisterRegister(.@"and", dst, imm);
4560 try self.asmRegisterImmediate(.{ ._, .mov }, imm, imm_0000_1111);
4561 try self.asmRegisterRegister(.{ ._, .@"and" }, tmp, imm);
4562 try self.asmRegisterRegister(.{ ._, .@"and" }, dst, imm);
44754563 } else {
4476 try self.asmRegisterImmediate(.@"and", tmp, imm_0000_1111);
4477 try self.asmRegisterImmediate(.@"and", dst, imm_0000_1111);
4564 try self.asmRegisterImmediate(.{ ._, .@"and" }, tmp, imm_0000_1111);
4565 try self.asmRegisterImmediate(.{ ._, .@"and" }, dst, imm_0000_1111);
44784566 }
44794567 // tmp = temp1 & 0x0F...0F
44804568 // dst = (temp1 >> 4) & 0x0F...0F
4481 try self.asmRegisterImmediate(.shl, tmp, Immediate.u(4));
4569 try self.asmRegisterImmediate(.{ ._l, .sh }, tmp, Immediate.u(4));
44824570 // tmp = (temp1 & 0x0F...0F) << 4
4483 try self.asmRegisterRegister(.@"or", dst, tmp);
4571 try self.asmRegisterRegister(.{ ._, .@"or" }, dst, tmp);
44844572 // dst = temp2 = ((temp1 >> 4) & 0x0F...0F) | ((temp1 & 0x0F...0F) << 4)
4485 try self.asmRegisterRegister(.mov, tmp, dst);
4573 try self.asmRegisterRegister(.{ ._, .mov }, tmp, dst);
44864574 // tmp = temp2
4487 try self.asmRegisterImmediate(.shr, dst, Immediate.u(2));
4575 try self.asmRegisterImmediate(.{ ._r, .sh }, dst, Immediate.u(2));
44884576 // dst = temp2 >> 2
44894577 if (src_abi_size > 4) {
4490 try self.asmRegisterImmediate(.mov, imm, imm_00_11);
4491 try self.asmRegisterRegister(.@"and", tmp, imm);
4492 try self.asmRegisterRegister(.@"and", dst, imm);
4578 try self.asmRegisterImmediate(.{ ._, .mov }, imm, imm_00_11);
4579 try self.asmRegisterRegister(.{ ._, .@"and" }, tmp, imm);
4580 try self.asmRegisterRegister(.{ ._, .@"and" }, dst, imm);
44934581 } else {
4494 try self.asmRegisterImmediate(.@"and", tmp, imm_00_11);
4495 try self.asmRegisterImmediate(.@"and", dst, imm_00_11);
4582 try self.asmRegisterImmediate(.{ ._, .@"and" }, tmp, imm_00_11);
4583 try self.asmRegisterImmediate(.{ ._, .@"and" }, dst, imm_00_11);
44964584 }
44974585 // tmp = temp2 & 0x33...33
44984586 // dst = (temp2 >> 2) & 0x33...33
44994587 try self.asmRegisterMemory(
4500 .lea,
4588 .{ ._, .lea },
45014589 if (src_abi_size > 4) tmp.to64() else tmp.to32(),
45024590 Memory.sib(.qword, .{
45034591 .base = .{ .reg = dst.to64() },
......@@ -4505,22 +4593,22 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
45054593 }),
45064594 );
45074595 // tmp = temp3 = ((temp2 >> 2) & 0x33...33) + ((temp2 & 0x33...33) << 2)
4508 try self.asmRegisterRegister(.mov, dst, tmp);
4596 try self.asmRegisterRegister(.{ ._, .mov }, dst, tmp);
45094597 // dst = temp3
4510 try self.asmRegisterImmediate(.shr, tmp, Immediate.u(1));
4598 try self.asmRegisterImmediate(.{ ._r, .sh }, tmp, Immediate.u(1));
45114599 // tmp = temp3 >> 1
45124600 if (src_abi_size > 4) {
4513 try self.asmRegisterImmediate(.mov, imm, imm_0_1);
4514 try self.asmRegisterRegister(.@"and", dst, imm);
4515 try self.asmRegisterRegister(.@"and", tmp, imm);
4601 try self.asmRegisterImmediate(.{ ._, .mov }, imm, imm_0_1);
4602 try self.asmRegisterRegister(.{ ._, .@"and" }, dst, imm);
4603 try self.asmRegisterRegister(.{ ._, .@"and" }, tmp, imm);
45164604 } else {
4517 try self.asmRegisterImmediate(.@"and", dst, imm_0_1);
4518 try self.asmRegisterImmediate(.@"and", tmp, imm_0_1);
4605 try self.asmRegisterImmediate(.{ ._, .@"and" }, dst, imm_0_1);
4606 try self.asmRegisterImmediate(.{ ._, .@"and" }, tmp, imm_0_1);
45194607 }
45204608 // dst = temp3 & 0x55...55
45214609 // tmp = (temp3 >> 1) & 0x55...55
45224610 try self.asmRegisterMemory(
4523 .lea,
4611 .{ ._, .lea },
45244612 if (src_abi_size > 4) dst.to64() else dst.to32(),
45254613 Memory.sib(.qword, .{
45264614 .base = .{ .reg = tmp.to64() },
......@@ -4533,7 +4621,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
45334621 switch (self.regExtraBits(src_ty)) {
45344622 0 => {},
45354623 else => |extra| try self.genBinOpMir(
4536 if (src_ty.isSignedInt()) .sar else .shr,
4624 if (src_ty.isSignedInt()) .{ ._r, .sa } else .{ ._r, .sh },
45374625 src_ty,
45384626 dst_mcv,
45394627 .{ .immediate = extra },
......@@ -4590,8 +4678,8 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
45904678 try self.genBinOpMir(switch (ty_bits) {
45914679 // No point using an extra prefix byte for *pd which performs the same operation.
45924680 16, 32, 64, 128 => switch (tag) {
4593 .neg => .xorps,
4594 .fabs => .andnps,
4681 .neg => .{ ._, .xorps },
4682 .fabs => .{ ._, .andnps },
45954683 else => unreachable,
45964684 },
45974685 80 => return self.fail("TODO implement airFloatSign for {}", .{
......@@ -4622,25 +4710,25 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4
46224710 if (!self.hasFeature(.sse4_1))
46234711 return self.fail("TODO implement genRound without sse4_1 feature", .{});
46244712
4625 const mir_tag = if (@as(?Mir.Inst.Tag, switch (ty.zigTypeTag()) {
4713 const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag()) {
46264714 .Float => switch (ty.floatBits(self.target.*)) {
4627 32 => if (self.hasFeature(.avx)) .vroundss else .roundss,
4628 64 => if (self.hasFeature(.avx)) .vroundsd else .roundsd,
4715 32 => if (self.hasFeature(.avx)) .{ ._, .vroundss } else .{ ._, .roundss },
4716 64 => if (self.hasFeature(.avx)) .{ ._, .vroundsd } else .{ ._, .roundsd },
46294717 16, 80, 128 => null,
46304718 else => unreachable,
46314719 },
46324720 .Vector => switch (ty.childType().zigTypeTag()) {
46334721 .Float => switch (ty.childType().floatBits(self.target.*)) {
46344722 32 => switch (ty.vectorLen()) {
4635 1 => if (self.hasFeature(.avx)) .vroundss else .roundss,
4636 2...4 => if (self.hasFeature(.avx)) .vroundps else .roundps,
4637 5...8 => if (self.hasFeature(.avx)) .vroundps else null,
4723 1 => if (self.hasFeature(.avx)) .{ ._, .vroundss } else .{ ._, .roundss },
4724 2...4 => if (self.hasFeature(.avx)) .{ ._, .vroundps } else .{ ._, .roundps },
4725 5...8 => if (self.hasFeature(.avx)) .{ ._, .vroundps } else null,
46384726 else => null,
46394727 },
46404728 64 => switch (ty.vectorLen()) {
4641 1 => if (self.hasFeature(.avx)) .vroundsd else .roundsd,
4642 2 => if (self.hasFeature(.avx)) .vroundpd else .roundpd,
4643 3...4 => if (self.hasFeature(.avx)) .vroundpd else null,
4729 1 => if (self.hasFeature(.avx)) .{ ._, .vroundsd } else .{ ._, .roundsd },
4730 2 => if (self.hasFeature(.avx)) .{ ._, .vroundpd } else .{ ._, .roundpd },
4731 3...4 => if (self.hasFeature(.avx)) .{ ._, .vroundpd } else null,
46444732 else => null,
46454733 },
46464734 16, 80, 128 => null,
......@@ -4655,7 +4743,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4
46554743
46564744 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
46574745 const dst_alias = registerAlias(dst_reg, abi_size);
4658 switch (mir_tag) {
4746 switch (mir_tag[1]) {
46594747 .vroundss, .vroundsd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemoryImmediate(
46604748 mir_tag,
46614749 dst_alias,
......@@ -4704,25 +4792,25 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
47044792 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
47054793
47064794 const result: MCValue = result: {
4707 const mir_tag = if (@as(?Mir.Inst.Tag, switch (ty.zigTypeTag()) {
4795 const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag()) {
47084796 .Float => switch (ty.floatBits(self.target.*)) {
47094797 16 => if (self.hasFeature(.f16c)) {
47104798 const mat_src_reg = if (src_mcv.isRegister())
47114799 src_mcv.getReg().?
47124800 else
47134801 try self.copyToTmpRegister(ty, src_mcv);
4714 try self.asmRegisterRegister(.vcvtph2ps, dst_reg, mat_src_reg.to128());
4715 try self.asmRegisterRegisterRegister(.vsqrtss, dst_reg, dst_reg, dst_reg);
4802 try self.asmRegisterRegister(.{ ._, .vcvtph2ps }, dst_reg, mat_src_reg.to128());
4803 try self.asmRegisterRegisterRegister(.{ ._, .vsqrtss }, dst_reg, dst_reg, dst_reg);
47164804 try self.asmRegisterRegisterImmediate(
4717 .vcvtps2ph,
4805 .{ ._, .vcvtps2ph },
47184806 dst_reg,
47194807 dst_reg,
47204808 Immediate.u(0b1_00),
47214809 );
47224810 break :result dst_mcv;
47234811 } else null,
4724 32 => if (self.hasFeature(.avx)) .vsqrtss else .sqrtss,
4725 64 => if (self.hasFeature(.avx)) .vsqrtsd else .sqrtsd,
4812 32 => if (self.hasFeature(.avx)) .{ ._, .vsqrtss } else .{ ._, .sqrtss },
4813 64 => if (self.hasFeature(.avx)) .{ ._, .vsqrtsd } else .{ ._, .sqrtsd },
47264814 80, 128 => null,
47274815 else => unreachable,
47284816 },
......@@ -4731,16 +4819,21 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
47314819 16 => if (self.hasFeature(.f16c)) switch (ty.vectorLen()) {
47324820 1 => {
47334821 try self.asmRegisterRegister(
4734 .vcvtph2ps,
4822 .{ ._, .vcvtph2ps },
47354823 dst_reg,
47364824 (if (src_mcv.isRegister())
47374825 src_mcv.getReg().?
47384826 else
47394827 try self.copyToTmpRegister(ty, src_mcv)).to128(),
47404828 );
4741 try self.asmRegisterRegisterRegister(.vsqrtss, dst_reg, dst_reg, dst_reg);
4829 try self.asmRegisterRegisterRegister(
4830 .{ ._, .vsqrtss },
4831 dst_reg,
4832 dst_reg,
4833 dst_reg,
4834 );
47424835 try self.asmRegisterRegisterImmediate(
4743 .vcvtps2ph,
4836 .{ ._, .vcvtps2ph },
47444837 dst_reg,
47454838 dst_reg,
47464839 Immediate.u(0b1_00),
......@@ -4750,22 +4843,22 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
47504843 2...8 => {
47514844 const wide_reg = registerAlias(dst_reg, abi_size * 2);
47524845 if (src_mcv.isMemory()) try self.asmRegisterMemory(
4753 .vcvtph2ps,
4846 .{ ._, .vcvtph2ps },
47544847 wide_reg,
47554848 src_mcv.mem(Memory.PtrSize.fromSize(
47564849 @intCast(u32, @divExact(wide_reg.bitSize(), 16)),
47574850 )),
47584851 ) else try self.asmRegisterRegister(
4759 .vcvtph2ps,
4852 .{ ._, .vcvtph2ps },
47604853 wide_reg,
47614854 (if (src_mcv.isRegister())
47624855 src_mcv.getReg().?
47634856 else
47644857 try self.copyToTmpRegister(ty, src_mcv)).to128(),
47654858 );
4766 try self.asmRegisterRegister(.vsqrtps, wide_reg, wide_reg);
4859 try self.asmRegisterRegister(.{ ._, .vsqrtps }, wide_reg, wide_reg);
47674860 try self.asmRegisterRegisterImmediate(
4768 .vcvtps2ph,
4861 .{ ._, .vcvtps2ph },
47694862 dst_reg,
47704863 wide_reg,
47714864 Immediate.u(0b1_00),
......@@ -4775,15 +4868,15 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
47754868 else => null,
47764869 } else null,
47774870 32 => switch (ty.vectorLen()) {
4778 1 => if (self.hasFeature(.avx)) .vsqrtss else .sqrtss,
4779 2...4 => if (self.hasFeature(.avx)) .vsqrtps else .sqrtps,
4780 5...8 => if (self.hasFeature(.avx)) .vsqrtps else null,
4871 1 => if (self.hasFeature(.avx)) .{ ._, .vsqrtss } else .{ ._, .sqrtss },
4872 2...4 => if (self.hasFeature(.avx)) .{ ._, .vsqrtps } else .{ ._, .sqrtps },
4873 5...8 => if (self.hasFeature(.avx)) .{ ._, .vsqrtps } else null,
47814874 else => null,
47824875 },
47834876 64 => switch (ty.vectorLen()) {
4784 1 => if (self.hasFeature(.avx)) .vsqrtsd else .sqrtsd,
4785 2 => if (self.hasFeature(.avx)) .vsqrtpd else .sqrtpd,
4786 3...4 => if (self.hasFeature(.avx)) .vsqrtpd else null,
4877 1 => if (self.hasFeature(.avx)) .{ ._, .vsqrtsd } else .{ ._, .sqrtsd },
4878 2 => if (self.hasFeature(.avx)) .{ ._, .vsqrtpd } else .{ ._, .sqrtpd },
4879 3...4 => if (self.hasFeature(.avx)) .{ ._, .vsqrtpd } else null,
47874880 else => null,
47884881 },
47894882 80, 128 => null,
......@@ -4795,7 +4888,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
47954888 })) |tag| tag else return self.fail("TODO implement airSqrt for {}", .{
47964889 ty.fmt(self.bin_file.options.module.?),
47974890 });
4798 switch (mir_tag) {
4891 switch (mir_tag[1]) {
47994892 .vsqrtss, .vsqrtsd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
48004893 mir_tag,
48014894 dst_reg,
......@@ -4911,14 +5004,14 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn
49115004 if (load_abi_size <= 8) {
49125005 const load_reg = registerAlias(dst_reg, load_abi_size);
49135006 try self.asmRegisterMemory(
4914 .mov,
5007 .{ ._, .mov },
49155008 load_reg,
49165009 Memory.sib(Memory.PtrSize.fromSize(load_abi_size), .{
49175010 .base = .{ .reg = ptr_reg },
49185011 .disp = val_byte_off,
49195012 }),
49205013 );
4921 try self.asmRegisterImmediate(.shr, load_reg, Immediate.u(val_bit_off));
5014 try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(val_bit_off));
49225015 } else {
49235016 const tmp_reg = registerAlias(try self.register_manager.allocReg(null, gp), val_abi_size);
49245017 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
......@@ -4926,7 +5019,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn
49265019
49275020 const dst_alias = registerAlias(dst_reg, val_abi_size);
49285021 try self.asmRegisterMemory(
4929 .mov,
5022 .{ ._, .mov },
49305023 dst_alias,
49315024 Memory.sib(Memory.PtrSize.fromSize(val_abi_size), .{
49325025 .base = .{ .reg = ptr_reg },
......@@ -4934,14 +5027,19 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn
49345027 }),
49355028 );
49365029 try self.asmRegisterMemory(
4937 .mov,
5030 .{ ._, .mov },
49385031 tmp_reg,
49395032 Memory.sib(Memory.PtrSize.fromSize(val_abi_size), .{
49405033 .base = .{ .reg = ptr_reg },
49415034 .disp = val_byte_off + 1,
49425035 }),
49435036 );
4944 try self.asmRegisterRegisterImmediate(.shrd, dst_alias, tmp_reg, Immediate.u(val_bit_off));
5037 try self.asmRegisterRegisterImmediate(
5038 .{ ._rd, .sh },
5039 dst_alias,
5040 tmp_reg,
5041 Immediate.u(val_bit_off),
5042 );
49455043 }
49465044
49475045 if (val_extra_bits > 0) try self.truncateRegister(val_ty, dst_reg);
......@@ -5047,13 +5145,13 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In
50475145 const part_mask_not = part_mask ^
50485146 (@as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - limb_abi_bits));
50495147 if (limb_abi_size <= 4) {
5050 try self.asmMemoryImmediate(.@"and", limb_mem, Immediate.u(part_mask_not));
5148 try self.asmMemoryImmediate(.{ ._, .@"and" }, limb_mem, Immediate.u(part_mask_not));
50515149 } else if (math.cast(i32, @bitCast(i64, part_mask_not))) |small| {
5052 try self.asmMemoryImmediate(.@"and", limb_mem, Immediate.s(small));
5150 try self.asmMemoryImmediate(.{ ._, .@"and" }, limb_mem, Immediate.s(small));
50535151 } else {
50545152 const part_mask_reg = try self.register_manager.allocReg(null, gp);
5055 try self.asmRegisterImmediate(.mov, part_mask_reg, Immediate.u(part_mask_not));
5056 try self.asmMemoryRegister(.@"and", limb_mem, part_mask_reg);
5153 try self.asmRegisterImmediate(.{ ._, .mov }, part_mask_reg, Immediate.u(part_mask_not));
5154 try self.asmMemoryRegister(.{ ._, .@"and" }, limb_mem, part_mask_reg);
50575155 }
50585156
50595157 if (src_bit_size <= 64) {
......@@ -5064,14 +5162,26 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In
50645162
50655163 try self.genSetReg(tmp_reg, src_ty, src_mcv);
50665164 switch (limb_i) {
5067 0 => try self.genShiftBinOpMir(.shl, src_ty, tmp_mcv, .{ .immediate = src_bit_off }),
5068 1 => try self.genShiftBinOpMir(.shr, src_ty, tmp_mcv, .{
5069 .immediate = limb_abi_bits - src_bit_off,
5070 }),
5165 0 => try self.genShiftBinOpMir(
5166 .{ ._l, .sh },
5167 src_ty,
5168 tmp_mcv,
5169 .{ .immediate = src_bit_off },
5170 ),
5171 1 => try self.genShiftBinOpMir(
5172 .{ ._r, .sh },
5173 src_ty,
5174 tmp_mcv,
5175 .{ .immediate = limb_abi_bits - src_bit_off },
5176 ),
50715177 else => unreachable,
50725178 }
5073 try self.genBinOpMir(.@"and", src_ty, tmp_mcv, .{ .immediate = part_mask });
5074 try self.asmMemoryRegister(.@"or", limb_mem, registerAlias(tmp_reg, limb_abi_size));
5179 try self.genBinOpMir(.{ ._, .@"and" }, src_ty, tmp_mcv, .{ .immediate = part_mask });
5180 try self.asmMemoryRegister(
5181 .{ ._, .@"or" },
5182 limb_mem,
5183 registerAlias(tmp_reg, limb_abi_size),
5184 );
50755185 } else return self.fail("TODO: implement packed store of {}", .{
50765186 src_ty.fmt(self.bin_file.options.module.?),
50775187 });
......@@ -5171,7 +5281,7 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32
51715281 .load_tlv => |sym_index| .{ .lea_tlv = sym_index },
51725282 else => mcv,
51735283 });
5174 try self.genBinOpMir(.add, Type.usize, dst_mcv, .{ .register = offset_reg });
5284 try self.genBinOpMir(.{ ._, .add }, Type.usize, dst_mcv, .{ .register = offset_reg });
51755285 break :result dst_mcv;
51765286 },
51775287 .indirect => |reg_off| break :result .{ .indirect = .{
......@@ -5255,14 +5365,14 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
52555365 if (load_abi_size <= 8) {
52565366 const load_reg = registerAlias(dst_reg, load_abi_size);
52575367 try self.asmRegisterMemory(
5258 .mov,
5368 .{ ._, .mov },
52595369 load_reg,
52605370 Memory.sib(Memory.PtrSize.fromSize(load_abi_size), .{
52615371 .base = .{ .frame = frame_addr.index },
52625372 .disp = frame_addr.off + field_byte_off,
52635373 }),
52645374 );
5265 try self.asmRegisterImmediate(.shr, load_reg, Immediate.u(field_bit_off));
5375 try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(field_bit_off));
52665376 } else {
52675377 const tmp_reg = registerAlias(
52685378 try self.register_manager.allocReg(null, gp),
......@@ -5273,7 +5383,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
52735383
52745384 const dst_alias = registerAlias(dst_reg, field_abi_size);
52755385 try self.asmRegisterMemory(
5276 .mov,
5386 .{ ._, .mov },
52775387 dst_alias,
52785388 Memory.sib(Memory.PtrSize.fromSize(field_abi_size), .{
52795389 .base = .{ .frame = frame_addr.index },
......@@ -5281,7 +5391,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
52815391 }),
52825392 );
52835393 try self.asmRegisterMemory(
5284 .mov,
5394 .{ ._, .mov },
52855395 tmp_reg,
52865396 Memory.sib(Memory.PtrSize.fromSize(field_abi_size), .{
52875397 .base = .{ .frame = frame_addr.index },
......@@ -5289,7 +5399,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
52895399 }),
52905400 );
52915401 try self.asmRegisterRegisterImmediate(
5292 .shrd,
5402 .{ ._rd, .sh },
52935403 dst_alias,
52945404 tmp_reg,
52955405 Immediate.u(field_bit_off),
......@@ -5325,21 +5435,26 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
53255435 defer if (dst_mcv_lock) |lock| self.register_manager.unlockReg(lock);
53265436
53275437 // Shift by struct_field_offset.
5328 try self.genShiftBinOpMir(.shr, Type.usize, dst_mcv, .{ .immediate = field_off });
5438 try self.genShiftBinOpMir(
5439 .{ ._r, .sh },
5440 Type.usize,
5441 dst_mcv,
5442 .{ .immediate = field_off },
5443 );
53295444
53305445 // Mask to field_bit_size bits
53315446 const field_bit_size = field_ty.bitSize(self.target.*);
53325447 const mask = ~@as(u64, 0) >> @intCast(u6, 64 - field_bit_size);
53335448
53345449 const tmp_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = mask });
5335 try self.genBinOpMir(.@"and", Type.usize, dst_mcv, .{ .register = tmp_reg });
5450 try self.genBinOpMir(.{ ._, .@"and" }, Type.usize, dst_mcv, .{ .register = tmp_reg });
53365451
53375452 const signedness =
53385453 if (field_ty.isAbiInt()) field_ty.intInfo(self.target.*).signedness else .unsigned;
53395454 const field_byte_size = @intCast(u32, field_ty.abiSize(self.target.*));
53405455 if (signedness == .signed and field_byte_size < 8) {
53415456 try self.asmRegisterRegister(
5342 if (field_byte_size >= 4) .movsxd else .movsx,
5457 if (field_byte_size >= 4) .{ ._d, .movsx } else .{ ._, .movsx },
53435458 dst_mcv.register,
53445459 registerAlias(dst_mcv.register, field_byte_size),
53455460 );
......@@ -5451,17 +5566,17 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air:
54515566
54525567 if (limb_pl.base.tag == .int_unsigned and self.regExtraBits(limb_ty) > 0) {
54535568 const mask = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - limb_pl.data);
5454 try self.genBinOpMir(.xor, limb_ty, limb_mcv, .{ .immediate = mask });
5455 } else try self.genUnOpMir(.not, limb_ty, limb_mcv);
5569 try self.genBinOpMir(.{ ._, .xor }, limb_ty, limb_mcv, .{ .immediate = mask });
5570 } else try self.genUnOpMir(.{ ._, .not }, limb_ty, limb_mcv);
54565571 }
54575572 },
5458 .neg => try self.genUnOpMir(.neg, src_ty, dst_mcv),
5573 .neg => try self.genUnOpMir(.{ ._, .neg }, src_ty, dst_mcv),
54595574 else => unreachable,
54605575 }
54615576 return dst_mcv;
54625577}
54635578
5464fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue) !void {
5579fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MCValue) !void {
54655580 const abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
54665581 if (abi_size > 8) return self.fail("TODO implement {} for {}", .{
54675582 mir_tag,
......@@ -5504,7 +5619,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValue
55045619/// Clobbers .rcx for non-immediate shift value.
55055620fn genShiftBinOpMir(
55065621 self: *Self,
5507 tag: Mir.Inst.Tag,
5622 tag: Mir.Inst.FixedTag,
55085623 ty: Type,
55095624 lhs_mcv: MCValue,
55105625 shift_mcv: MCValue,
......@@ -5589,16 +5704,16 @@ fn genShiftBinOpMir(
55895704 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
55905705 defer self.register_manager.unlockReg(tmp_lock);
55915706
5592 const info: struct { offsets: [2]i32, double_tag: Mir.Inst.Tag } = switch (tag) {
5593 .shl, .sal => .{ .offsets = .{ 0, 8 }, .double_tag = .shld },
5594 .shr, .sar => .{ .offsets = .{ 8, 0 }, .double_tag = .shrd },
5707 const info: struct { offsets: [2]i32, double_tag: Mir.Inst.FixedTag } = switch (tag[0]) {
5708 ._l => .{ .offsets = .{ 0, 8 }, .double_tag = .{ ._ld, .sh } },
5709 ._r => .{ .offsets = .{ 8, 0 }, .double_tag = .{ ._rd, .sh } },
55955710 else => unreachable,
55965711 };
55975712 switch (lhs_mcv) {
55985713 .load_frame => |dst_frame_addr| switch (rhs_mcv) {
55995714 .immediate => |rhs_imm| if (rhs_imm == 0) {} else if (rhs_imm < 64) {
56005715 try self.asmRegisterMemory(
5601 .mov,
5716 .{ ._, .mov },
56025717 tmp_reg,
56035718 Memory.sib(.qword, .{
56045719 .base = .{ .frame = dst_frame_addr.index },
......@@ -5625,7 +5740,7 @@ fn genShiftBinOpMir(
56255740 } else {
56265741 assert(rhs_imm < 128);
56275742 try self.asmRegisterMemory(
5628 .mov,
5743 .{ ._, .mov },
56295744 tmp_reg,
56305745 Memory.sib(.qword, .{
56315746 .base = .{ .frame = dst_frame_addr.index },
......@@ -5636,34 +5751,30 @@ fn genShiftBinOpMir(
56365751 try self.asmRegisterImmediate(tag, tmp_reg, Immediate.u(rhs_imm - 64));
56375752 }
56385753 try self.asmMemoryRegister(
5639 .mov,
5754 .{ ._, .mov },
56405755 Memory.sib(.qword, .{
56415756 .base = .{ .frame = dst_frame_addr.index },
56425757 .disp = dst_frame_addr.off + info.offsets[1],
56435758 }),
56445759 tmp_reg,
56455760 );
5646 switch (tag) {
5647 .shl, .sal, .shr => {
5648 try self.asmRegisterRegister(.xor, tmp_reg.to32(), tmp_reg.to32());
5649 try self.asmMemoryRegister(
5650 .mov,
5651 Memory.sib(.qword, .{
5652 .base = .{ .frame = dst_frame_addr.index },
5653 .disp = dst_frame_addr.off + info.offsets[0],
5654 }),
5655 tmp_reg,
5656 );
5657 },
5658 .sar => try self.asmMemoryImmediate(
5659 tag,
5761 if (tag[0] == ._r and tag[1] == .sa) try self.asmMemoryImmediate(
5762 tag,
5763 Memory.sib(.qword, .{
5764 .base = .{ .frame = dst_frame_addr.index },
5765 .disp = dst_frame_addr.off + info.offsets[0],
5766 }),
5767 Immediate.u(63),
5768 ) else {
5769 try self.asmRegisterRegister(.{ ._, .xor }, tmp_reg.to32(), tmp_reg.to32());
5770 try self.asmMemoryRegister(
5771 .{ ._, .mov },
56605772 Memory.sib(.qword, .{
56615773 .base = .{ .frame = dst_frame_addr.index },
56625774 .disp = dst_frame_addr.off + info.offsets[0],
56635775 }),
5664 Immediate.u(63),
5665 ),
5666 else => unreachable,
5776 tmp_reg,
5777 );
56675778 }
56685779 },
56695780 else => {
......@@ -5677,7 +5788,7 @@ fn genShiftBinOpMir(
56775788
56785789 try self.genSetReg(.cl, Type.u8, rhs_mcv);
56795790 try self.asmRegisterMemory(
5680 .mov,
5791 .{ ._, .mov },
56815792 first_reg,
56825793 Memory.sib(.qword, .{
56835794 .base = .{ .frame = dst_frame_addr.index },
......@@ -5685,32 +5796,28 @@ fn genShiftBinOpMir(
56855796 }),
56865797 );
56875798 try self.asmRegisterMemory(
5688 .mov,
5799 .{ ._, .mov },
56895800 second_reg,
56905801 Memory.sib(.qword, .{
56915802 .base = .{ .frame = dst_frame_addr.index },
56925803 .disp = dst_frame_addr.off + info.offsets[1],
56935804 }),
56945805 );
5695 switch (tag) {
5696 .shl, .sal, .shr => try self.asmRegisterRegister(
5697 .xor,
5698 tmp_reg.to32(),
5699 tmp_reg.to32(),
5700 ),
5701 .sar => {
5702 try self.asmRegisterRegister(.mov, tmp_reg, first_reg);
5703 try self.asmRegisterImmediate(tag, tmp_reg, Immediate.u(63));
5704 },
5705 else => unreachable,
5706 }
5806 if (tag[0] == ._r and tag[1] == .sa) {
5807 try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, first_reg);
5808 try self.asmRegisterImmediate(tag, tmp_reg, Immediate.u(63));
5809 } else try self.asmRegisterRegister(
5810 .{ ._, .xor },
5811 tmp_reg.to32(),
5812 tmp_reg.to32(),
5813 );
57075814 try self.asmRegisterRegisterRegister(info.double_tag, second_reg, first_reg, .cl);
57085815 try self.asmRegisterRegister(tag, first_reg, .cl);
5709 try self.asmRegisterImmediate(.cmp, .cl, Immediate.u(64));
5816 try self.asmRegisterImmediate(.{ ._, .cmp }, .cl, Immediate.u(64));
57105817 try self.asmCmovccRegisterRegister(second_reg, first_reg, .ae);
57115818 try self.asmCmovccRegisterRegister(first_reg, tmp_reg, .ae);
57125819 try self.asmMemoryRegister(
5713 .mov,
5820 .{ ._, .mov },
57145821 Memory.sib(.qword, .{
57155822 .base = .{ .frame = dst_frame_addr.index },
57165823 .disp = dst_frame_addr.off + info.offsets[1],
......@@ -5718,7 +5825,7 @@ fn genShiftBinOpMir(
57185825 second_reg,
57195826 );
57205827 try self.asmMemoryRegister(
5721 .mov,
5828 .{ ._, .mov },
57225829 Memory.sib(.qword, .{
57235830 .base = .{ .frame = dst_frame_addr.index },
57245831 .disp = dst_frame_addr.off + info.offsets[0],
......@@ -5743,7 +5850,7 @@ fn genShiftBinOpMir(
57435850/// Asserts .rcx is free.
57445851fn genShiftBinOp(
57455852 self: *Self,
5746 tag: Air.Inst.Tag,
5853 air_tag: Air.Inst.Tag,
57475854 maybe_inst: ?Air.Inst.Index,
57485855 lhs_mcv: MCValue,
57495856 rhs_mcv: MCValue,
......@@ -5788,14 +5895,14 @@ fn genShiftBinOp(
57885895 };
57895896
57905897 const signedness = lhs_ty.intInfo(self.target.*).signedness;
5791 try self.genShiftBinOpMir(switch (tag) {
5898 try self.genShiftBinOpMir(switch (air_tag) {
57925899 .shl, .shl_exact => switch (signedness) {
5793 .signed => .sal,
5794 .unsigned => .shl,
5900 .signed => .{ ._l, .sa },
5901 .unsigned => .{ ._l, .sh },
57955902 },
57965903 .shr, .shr_exact => switch (signedness) {
5797 .signed => .sar,
5798 .unsigned => .shr,
5904 .signed => .{ ._r, .sa },
5905 .unsigned => .{ ._r, .sh },
57995906 },
58005907 else => unreachable,
58015908 }, lhs_ty, dst_mcv, rhs_mcv);
......@@ -5855,20 +5962,18 @@ fn genMulDivBinOp(
58555962 try self.register_manager.getReg(.rax, track_inst_rax);
58565963 try self.register_manager.getReg(.rdx, track_inst_rdx);
58575964
5858 const mir_tag: Mir.Inst.Tag = switch (signedness) {
5965 try self.genIntMulDivOpMir(switch (signedness) {
58595966 .signed => switch (tag) {
5860 .mul, .mulwrap => .imul,
5861 .div_trunc, .div_exact, .rem => .idiv,
5967 .mul, .mulwrap => .{ .i_, .mul },
5968 .div_trunc, .div_exact, .rem => .{ .i_, .div },
58625969 else => unreachable,
58635970 },
58645971 .unsigned => switch (tag) {
5865 .mul, .mulwrap => .mul,
5866 .div_trunc, .div_exact, .rem => .div,
5972 .mul, .mulwrap => .{ ._, .mul },
5973 .div_trunc, .div_exact, .rem => .{ ._, .div },
58675974 else => unreachable,
58685975 },
5869 };
5870
5871 try self.genIntMulDivOpMir(mir_tag, ty, lhs, rhs);
5976 }, ty, lhs, rhs);
58725977
58735978 if (dst_abi_size <= 8) return .{ .register = registerAlias(switch (tag) {
58745979 .mul, .mulwrap, .div_trunc, .div_exact => .rax,
......@@ -5878,7 +5983,7 @@ fn genMulDivBinOp(
58785983
58795984 const dst_mcv = try self.allocRegOrMemAdvanced(dst_ty, maybe_inst, false);
58805985 try self.asmMemoryRegister(
5881 .mov,
5986 .{ ._, .mov },
58825987 Memory.sib(.qword, .{
58835988 .base = .{ .frame = dst_mcv.load_frame.index },
58845989 .disp = dst_mcv.load_frame.off,
......@@ -5886,7 +5991,7 @@ fn genMulDivBinOp(
58865991 .rax,
58875992 );
58885993 try self.asmMemoryRegister(
5889 .mov,
5994 .{ ._, .mov },
58905995 Memory.sib(.qword, .{
58915996 .base = .{ .frame = dst_mcv.load_frame.index },
58925997 .disp = dst_mcv.load_frame.off + 8,
......@@ -5927,12 +6032,12 @@ fn genMulDivBinOp(
59276032 try self.copyToRegisterWithInstTracking(inst, ty, lhs)
59286033 else
59296034 .{ .register = try self.copyToTmpRegister(ty, lhs) };
5930 try self.genBinOpMir(.sub, ty, result, div_floor);
6035 try self.genBinOpMir(.{ ._, .sub }, ty, result, div_floor);
59316036
59326037 return result;
59336038 },
59346039 .unsigned => {
5935 try self.genIntMulDivOpMir(.div, ty, lhs, rhs);
6040 try self.genIntMulDivOpMir(.{ ._, .div }, ty, lhs, rhs);
59366041 return .{ .register = registerAlias(.rdx, abi_size) };
59376042 },
59386043 }
......@@ -5974,7 +6079,7 @@ fn genMulDivBinOp(
59746079 switch (signedness) {
59756080 .signed => return try self.genInlineIntDivFloor(ty, lhs, actual_rhs),
59766081 .unsigned => {
5977 try self.genIntMulDivOpMir(.div, ty, lhs, actual_rhs);
6082 try self.genIntMulDivOpMir(.{ ._, .div }, ty, lhs, actual_rhs);
59786083 return .{ .register = registerAlias(.rax, abi_size) };
59796084 },
59806085 }
......@@ -6072,11 +6177,11 @@ fn genBinOp(
60726177 switch (air_tag) {
60736178 .add,
60746179 .addwrap,
6075 => try self.genBinOpMir(.add, lhs_ty, dst_mcv, src_mcv),
6180 => try self.genBinOpMir(.{ ._, .add }, lhs_ty, dst_mcv, src_mcv),
60766181
60776182 .sub,
60786183 .subwrap,
6079 => try self.genBinOpMir(.sub, lhs_ty, dst_mcv, src_mcv),
6184 => try self.genBinOpMir(.{ ._, .sub }, lhs_ty, dst_mcv, src_mcv),
60806185
60816186 .ptr_add,
60826187 .ptr_sub,
......@@ -6088,22 +6193,27 @@ fn genBinOp(
60886193
60896194 const elem_size = lhs_ty.elemType2().abiSize(self.target.*);
60906195 try self.genIntMulComplexOpMir(rhs_ty, tmp_mcv, .{ .immediate = elem_size });
6091 try self.genBinOpMir(switch (air_tag) {
6092 .ptr_add => .add,
6093 .ptr_sub => .sub,
6094 else => unreachable,
6095 }, lhs_ty, dst_mcv, tmp_mcv);
6196 try self.genBinOpMir(
6197 switch (air_tag) {
6198 .ptr_add => .{ ._, .add },
6199 .ptr_sub => .{ ._, .sub },
6200 else => unreachable,
6201 },
6202 lhs_ty,
6203 dst_mcv,
6204 tmp_mcv,
6205 );
60966206 },
60976207
60986208 .bool_or,
60996209 .bit_or,
6100 => try self.genBinOpMir(.@"or", lhs_ty, dst_mcv, src_mcv),
6210 => try self.genBinOpMir(.{ ._, .@"or" }, lhs_ty, dst_mcv, src_mcv),
61016211
61026212 .bool_and,
61036213 .bit_and,
6104 => try self.genBinOpMir(.@"and", lhs_ty, dst_mcv, src_mcv),
6214 => try self.genBinOpMir(.{ ._, .@"and" }, lhs_ty, dst_mcv, src_mcv),
61056215
6106 .xor => try self.genBinOpMir(.xor, lhs_ty, dst_mcv, src_mcv),
6216 .xor => try self.genBinOpMir(.{ ._, .xor }, lhs_ty, dst_mcv, src_mcv),
61076217
61086218 .min,
61096219 .max,
......@@ -6129,7 +6239,7 @@ fn genBinOp(
61296239 };
61306240 defer if (mat_mcv_lock) |lock| self.register_manager.unlockReg(lock);
61316241
6132 try self.genBinOpMir(.cmp, lhs_ty, dst_mcv, mat_src_mcv);
6242 try self.genBinOpMir(.{ ._, .cmp }, lhs_ty, dst_mcv, mat_src_mcv);
61336243
61346244 const int_info = lhs_ty.intInfo(self.target.*);
61356245 const cc: Condition = switch (int_info.signedness) {
......@@ -6206,7 +6316,7 @@ fn genBinOp(
62066316 }
62076317
62086318 const dst_reg = registerAlias(dst_mcv.getReg().?, abi_size);
6209 const mir_tag = if (@as(?Mir.Inst.Tag, switch (lhs_ty.zigTypeTag()) {
6319 const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {
62106320 else => unreachable,
62116321 .Float => switch (lhs_ty.floatBits(self.target.*)) {
62126322 16 => if (self.hasFeature(.f16c)) {
......@@ -6215,13 +6325,13 @@ fn genBinOp(
62156325 defer self.register_manager.unlockReg(tmp_lock);
62166326
62176327 if (src_mcv.isMemory()) try self.asmRegisterRegisterMemoryImmediate(
6218 .vpinsrw,
6328 .{ ._, .vpinsrw },
62196329 dst_reg,
62206330 dst_reg,
62216331 src_mcv.mem(.word),
62226332 Immediate.u(1),
62236333 ) else try self.asmRegisterRegisterRegister(
6224 .vpunpcklwd,
6334 .{ ._, .vpunpcklwd },
62256335 dst_reg,
62266336 dst_reg,
62276337 (if (src_mcv.isRegister())
......@@ -6229,15 +6339,15 @@ fn genBinOp(
62296339 else
62306340 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
62316341 );
6232 try self.asmRegisterRegister(.vcvtph2ps, dst_reg, dst_reg);
6233 try self.asmRegisterRegister(.vmovshdup, tmp_reg, dst_reg);
6342 try self.asmRegisterRegister(.{ ._, .vcvtph2ps }, dst_reg, dst_reg);
6343 try self.asmRegisterRegister(.{ ._, .vmovshdup }, tmp_reg, dst_reg);
62346344 try self.asmRegisterRegisterRegister(
62356345 switch (air_tag) {
6236 .add => .vaddss,
6237 .sub => .vsubss,
6238 .div_float, .div_trunc, .div_floor, .div_exact => .vdivss,
6239 .max => .vmaxss,
6240 .min => .vmaxss,
6346 .add => .{ ._, .vaddss },
6347 .sub => .{ ._, .vsubss },
6348 .div_float, .div_trunc, .div_floor, .div_exact => .{ ._, .vdivss },
6349 .max => .{ ._, .vmaxss },
6350 .min => .{ ._, .vmaxss },
62416351 else => unreachable,
62426352 },
62436353 dst_reg,
......@@ -6245,7 +6355,7 @@ fn genBinOp(
62456355 tmp_reg,
62466356 );
62476357 try self.asmRegisterRegisterImmediate(
6248 .vcvtps2ph,
6358 .{ ._, .vcvtps2ph },
62496359 dst_reg,
62506360 dst_reg,
62516361 Immediate.u(0b1_00),
......@@ -6253,29 +6363,29 @@ fn genBinOp(
62536363 return dst_mcv;
62546364 } else null,
62556365 32 => switch (air_tag) {
6256 .add => if (self.hasFeature(.avx)) .vaddss else .addss,
6257 .sub => if (self.hasFeature(.avx)) .vsubss else .subss,
6258 .mul => if (self.hasFeature(.avx)) .vmulss else .mulss,
6366 .add => if (self.hasFeature(.avx)) .{ ._, .vaddss } else .{ ._, .addss },
6367 .sub => if (self.hasFeature(.avx)) .{ ._, .vsubss } else .{ ._, .subss },
6368 .mul => if (self.hasFeature(.avx)) .{ ._, .vmulss } else .{ ._, .mulss },
62596369 .div_float,
62606370 .div_trunc,
62616371 .div_floor,
62626372 .div_exact,
6263 => if (self.hasFeature(.avx)) .vdivss else .divss,
6264 .max => if (self.hasFeature(.avx)) .vmaxss else .maxss,
6265 .min => if (self.hasFeature(.avx)) .vminss else .minss,
6373 => if (self.hasFeature(.avx)) .{ ._, .vdivss } else .{ ._, .divss },
6374 .max => if (self.hasFeature(.avx)) .{ ._, .vmaxss } else .{ ._, .maxss },
6375 .min => if (self.hasFeature(.avx)) .{ ._, .vminss } else .{ ._, .minss },
62666376 else => unreachable,
62676377 },
62686378 64 => switch (air_tag) {
6269 .add => if (self.hasFeature(.avx)) .vaddsd else .addsd,
6270 .sub => if (self.hasFeature(.avx)) .vsubsd else .subsd,
6271 .mul => if (self.hasFeature(.avx)) .vmulsd else .mulsd,
6379 .add => if (self.hasFeature(.avx)) .{ ._, .vaddsd } else .{ ._, .addsd },
6380 .sub => if (self.hasFeature(.avx)) .{ ._, .vsubsd } else .{ ._, .subsd },
6381 .mul => if (self.hasFeature(.avx)) .{ ._, .vmulsd } else .{ ._, .mulsd },
62726382 .div_float,
62736383 .div_trunc,
62746384 .div_floor,
62756385 .div_exact,
6276 => if (self.hasFeature(.avx)) .vdivsd else .divsd,
6277 .max => if (self.hasFeature(.avx)) .vmaxsd else .maxsd,
6278 .min => if (self.hasFeature(.avx)) .vminsd else .minsd,
6386 => if (self.hasFeature(.avx)) .{ ._, .vdivsd } else .{ ._, .divsd },
6387 .max => if (self.hasFeature(.avx)) .{ ._, .vmaxsd } else .{ ._, .maxsd },
6388 .min => if (self.hasFeature(.avx)) .{ ._, .vminsd } else .{ ._, .minsd },
62796389 else => unreachable,
62806390 },
62816391 80, 128 => null,
......@@ -6291,13 +6401,13 @@ fn genBinOp(
62916401 defer self.register_manager.unlockReg(tmp_lock);
62926402
62936403 if (src_mcv.isMemory()) try self.asmRegisterRegisterMemoryImmediate(
6294 .vpinsrw,
6404 .{ ._, .vpinsrw },
62956405 dst_reg,
62966406 dst_reg,
62976407 src_mcv.mem(.word),
62986408 Immediate.u(1),
62996409 ) else try self.asmRegisterRegisterRegister(
6300 .vpunpcklwd,
6410 .{ ._, .vpunpcklwd },
63016411 dst_reg,
63026412 dst_reg,
63036413 (if (src_mcv.isRegister())
......@@ -6305,15 +6415,15 @@ fn genBinOp(
63056415 else
63066416 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
63076417 );
6308 try self.asmRegisterRegister(.vcvtph2ps, dst_reg, dst_reg);
6309 try self.asmRegisterRegister(.vmovshdup, tmp_reg, dst_reg);
6418 try self.asmRegisterRegister(.{ ._, .vcvtph2ps }, dst_reg, dst_reg);
6419 try self.asmRegisterRegister(.{ ._, .vmovshdup }, tmp_reg, dst_reg);
63106420 try self.asmRegisterRegisterRegister(
63116421 switch (air_tag) {
6312 .add => .vaddss,
6313 .sub => .vsubss,
6314 .div_float, .div_trunc, .div_floor, .div_exact => .vdivss,
6315 .max => .vmaxss,
6316 .min => .vmaxss,
6422 .add => .{ ._, .vaddss },
6423 .sub => .{ ._, .vsubss },
6424 .div_float, .div_trunc, .div_floor, .div_exact => .{ ._, .vdivss },
6425 .max => .{ ._, .vmaxss },
6426 .min => .{ ._, .vmaxss },
63176427 else => unreachable,
63186428 },
63196429 dst_reg,
......@@ -6321,7 +6431,7 @@ fn genBinOp(
63216431 tmp_reg,
63226432 );
63236433 try self.asmRegisterRegisterImmediate(
6324 .vcvtps2ph,
6434 .{ ._, .vcvtps2ph },
63256435 dst_reg,
63266436 dst_reg,
63276437 Immediate.u(0b1_00),
......@@ -6334,12 +6444,12 @@ fn genBinOp(
63346444 defer self.register_manager.unlockReg(tmp_lock);
63356445
63366446 if (src_mcv.isMemory()) try self.asmRegisterMemoryImmediate(
6337 .vpinsrd,
6447 .{ ._, .vpinsrd },
63386448 dst_reg,
63396449 src_mcv.mem(.dword),
63406450 Immediate.u(1),
63416451 ) else try self.asmRegisterRegisterRegister(
6342 .vunpcklps,
6452 .{ ._, .vunpcklps },
63436453 dst_reg,
63446454 dst_reg,
63456455 (if (src_mcv.isRegister())
......@@ -6347,15 +6457,20 @@ fn genBinOp(
63476457 else
63486458 try self.copyToTmpRegister(rhs_ty, src_mcv)).to128(),
63496459 );
6350 try self.asmRegisterRegister(.vcvtph2ps, dst_reg, dst_reg);
6351 try self.asmRegisterRegisterRegister(.vmovhlps, tmp_reg, dst_reg, dst_reg);
6460 try self.asmRegisterRegister(.{ ._, .vcvtph2ps }, dst_reg, dst_reg);
6461 try self.asmRegisterRegisterRegister(
6462 .{ ._, .vmovhlps },
6463 tmp_reg,
6464 dst_reg,
6465 dst_reg,
6466 );
63526467 try self.asmRegisterRegisterRegister(
63536468 switch (air_tag) {
6354 .add => .vaddps,
6355 .sub => .vsubps,
6356 .div_float, .div_trunc, .div_floor, .div_exact => .vdivps,
6357 .max => .vmaxps,
6358 .min => .vmaxps,
6469 .add => .{ ._, .vaddps },
6470 .sub => .{ ._, .vsubps },
6471 .div_float, .div_trunc, .div_floor, .div_exact => .{ ._, .vdivps },
6472 .max => .{ ._, .vmaxps },
6473 .min => .{ ._, .vmaxps },
63596474 else => unreachable,
63606475 },
63616476 dst_reg,
......@@ -6363,7 +6478,7 @@ fn genBinOp(
63636478 tmp_reg,
63646479 );
63656480 try self.asmRegisterRegisterImmediate(
6366 .vcvtps2ph,
6481 .{ ._, .vcvtps2ph },
63676482 dst_reg,
63686483 dst_reg,
63696484 Immediate.u(0b1_00),
......@@ -6375,13 +6490,13 @@ fn genBinOp(
63756490 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
63766491 defer self.register_manager.unlockReg(tmp_lock);
63776492
6378 try self.asmRegisterRegister(.vcvtph2ps, dst_reg, dst_reg);
6493 try self.asmRegisterRegister(.{ ._, .vcvtph2ps }, dst_reg, dst_reg);
63796494 if (src_mcv.isMemory()) try self.asmRegisterMemory(
6380 .vcvtph2ps,
6495 .{ ._, .vcvtph2ps },
63816496 tmp_reg,
63826497 src_mcv.mem(.qword),
63836498 ) else try self.asmRegisterRegister(
6384 .vcvtph2ps,
6499 .{ ._, .vcvtph2ps },
63856500 tmp_reg,
63866501 (if (src_mcv.isRegister())
63876502 src_mcv.getReg().?
......@@ -6390,11 +6505,11 @@ fn genBinOp(
63906505 );
63916506 try self.asmRegisterRegisterRegister(
63926507 switch (air_tag) {
6393 .add => .vaddps,
6394 .sub => .vsubps,
6395 .div_float, .div_trunc, .div_floor, .div_exact => .vdivps,
6396 .max => .vmaxps,
6397 .min => .vmaxps,
6508 .add => .{ ._, .vaddps },
6509 .sub => .{ ._, .vsubps },
6510 .div_float, .div_trunc, .div_floor, .div_exact => .{ ._, .vdivps },
6511 .max => .{ ._, .vmaxps },
6512 .min => .{ ._, .vmaxps },
63986513 else => unreachable,
63996514 },
64006515 dst_reg,
......@@ -6402,7 +6517,7 @@ fn genBinOp(
64026517 tmp_reg,
64036518 );
64046519 try self.asmRegisterRegisterImmediate(
6405 .vcvtps2ph,
6520 .{ ._, .vcvtps2ph },
64066521 dst_reg,
64076522 dst_reg,
64086523 Immediate.u(0b1_00),
......@@ -6414,13 +6529,13 @@ fn genBinOp(
64146529 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
64156530 defer self.register_manager.unlockReg(tmp_lock);
64166531
6417 try self.asmRegisterRegister(.vcvtph2ps, dst_reg.to256(), dst_reg);
6532 try self.asmRegisterRegister(.{ ._, .vcvtph2ps }, dst_reg.to256(), dst_reg);
64186533 if (src_mcv.isMemory()) try self.asmRegisterMemory(
6419 .vcvtph2ps,
6534 .{ ._, .vcvtph2ps },
64206535 tmp_reg,
64216536 src_mcv.mem(.xword),
64226537 ) else try self.asmRegisterRegister(
6423 .vcvtph2ps,
6538 .{ ._, .vcvtph2ps },
64246539 tmp_reg,
64256540 (if (src_mcv.isRegister())
64266541 src_mcv.getReg().?
......@@ -6429,11 +6544,11 @@ fn genBinOp(
64296544 );
64306545 try self.asmRegisterRegisterRegister(
64316546 switch (air_tag) {
6432 .add => .vaddps,
6433 .sub => .vsubps,
6434 .div_float, .div_trunc, .div_floor, .div_exact => .vdivps,
6435 .max => .vmaxps,
6436 .min => .vmaxps,
6547 .add => .{ ._, .vaddps },
6548 .sub => .{ ._, .vsubps },
6549 .div_float, .div_trunc, .div_floor, .div_exact => .{ ._, .vdivps },
6550 .max => .{ ._, .vmaxps },
6551 .min => .{ ._, .vmaxps },
64376552 else => unreachable,
64386553 },
64396554 dst_reg.to256(),
......@@ -6441,7 +6556,7 @@ fn genBinOp(
64416556 tmp_reg,
64426557 );
64436558 try self.asmRegisterRegisterImmediate(
6444 .vcvtps2ph,
6559 .{ ._, .vcvtps2ph },
64456560 dst_reg,
64466561 dst_reg.to256(),
64476562 Immediate.u(0b1_00),
......@@ -6452,76 +6567,76 @@ fn genBinOp(
64526567 } else null,
64536568 32 => switch (lhs_ty.vectorLen()) {
64546569 1 => switch (air_tag) {
6455 .add => if (self.hasFeature(.avx)) .vaddss else .addss,
6456 .sub => if (self.hasFeature(.avx)) .vsubss else .subss,
6457 .mul => if (self.hasFeature(.avx)) .vmulss else .mulss,
6570 .add => if (self.hasFeature(.avx)) .{ ._, .vaddss } else .{ ._, .addss },
6571 .sub => if (self.hasFeature(.avx)) .{ ._, .vsubss } else .{ ._, .subss },
6572 .mul => if (self.hasFeature(.avx)) .{ ._, .vmulss } else .{ ._, .mulss },
64586573 .div_float,
64596574 .div_trunc,
64606575 .div_floor,
64616576 .div_exact,
6462 => if (self.hasFeature(.avx)) .vdivss else .divss,
6463 .max => if (self.hasFeature(.avx)) .vmaxss else .maxss,
6464 .min => if (self.hasFeature(.avx)) .vminss else .minss,
6577 => if (self.hasFeature(.avx)) .{ ._, .vdivss } else .{ ._, .divss },
6578 .max => if (self.hasFeature(.avx)) .{ ._, .vmaxss } else .{ ._, .maxss },
6579 .min => if (self.hasFeature(.avx)) .{ ._, .vminss } else .{ ._, .minss },
64656580 else => unreachable,
64666581 },
64676582 2...4 => switch (air_tag) {
6468 .add => if (self.hasFeature(.avx)) .vaddps else .addps,
6469 .sub => if (self.hasFeature(.avx)) .vsubps else .subps,
6470 .mul => if (self.hasFeature(.avx)) .vmulps else .mulps,
6583 .add => if (self.hasFeature(.avx)) .{ ._, .vaddps } else .{ ._, .addps },
6584 .sub => if (self.hasFeature(.avx)) .{ ._, .vsubps } else .{ ._, .subps },
6585 .mul => if (self.hasFeature(.avx)) .{ ._, .vmulps } else .{ ._, .mulps },
64716586 .div_float,
64726587 .div_trunc,
64736588 .div_floor,
64746589 .div_exact,
6475 => if (self.hasFeature(.avx)) .vdivps else .divps,
6476 .max => if (self.hasFeature(.avx)) .vmaxps else .maxps,
6477 .min => if (self.hasFeature(.avx)) .vminps else .minps,
6590 => if (self.hasFeature(.avx)) .{ ._, .vdivps } else .{ ._, .divps },
6591 .max => if (self.hasFeature(.avx)) .{ ._, .vmaxps } else .{ ._, .maxps },
6592 .min => if (self.hasFeature(.avx)) .{ ._, .vminps } else .{ ._, .minps },
64786593 else => unreachable,
64796594 },
64806595 5...8 => if (self.hasFeature(.avx)) switch (air_tag) {
6481 .add => .vaddps,
6482 .sub => .vsubps,
6483 .mul => .vmulps,
6484 .div_float, .div_trunc, .div_floor, .div_exact => .vdivps,
6485 .max => .vmaxps,
6486 .min => .vminps,
6596 .add => .{ ._, .vaddps },
6597 .sub => .{ ._, .vsubps },
6598 .mul => .{ ._, .vmulps },
6599 .div_float, .div_trunc, .div_floor, .div_exact => .{ ._, .vdivps },
6600 .max => .{ ._, .vmaxps },
6601 .min => .{ ._, .vminps },
64876602 else => unreachable,
64886603 } else null,
64896604 else => null,
64906605 },
64916606 64 => switch (lhs_ty.vectorLen()) {
64926607 1 => switch (air_tag) {
6493 .add => if (self.hasFeature(.avx)) .vaddsd else .addsd,
6494 .sub => if (self.hasFeature(.avx)) .vsubsd else .subsd,
6495 .mul => if (self.hasFeature(.avx)) .vmulsd else .mulsd,
6608 .add => if (self.hasFeature(.avx)) .{ ._, .vaddsd } else .{ ._, .addsd },
6609 .sub => if (self.hasFeature(.avx)) .{ ._, .vsubsd } else .{ ._, .subsd },
6610 .mul => if (self.hasFeature(.avx)) .{ ._, .vmulsd } else .{ ._, .mulsd },
64966611 .div_float,
64976612 .div_trunc,
64986613 .div_floor,
64996614 .div_exact,
6500 => if (self.hasFeature(.avx)) .vdivsd else .divsd,
6501 .max => if (self.hasFeature(.avx)) .vmaxsd else .maxsd,
6502 .min => if (self.hasFeature(.avx)) .vminsd else .minsd,
6615 => if (self.hasFeature(.avx)) .{ ._, .vdivsd } else .{ ._, .divsd },
6616 .max => if (self.hasFeature(.avx)) .{ ._, .vmaxsd } else .{ ._, .maxsd },
6617 .min => if (self.hasFeature(.avx)) .{ ._, .vminsd } else .{ ._, .minsd },
65036618 else => unreachable,
65046619 },
65056620 2 => switch (air_tag) {
6506 .add => if (self.hasFeature(.avx)) .vaddpd else .addpd,
6507 .sub => if (self.hasFeature(.avx)) .vsubpd else .subpd,
6508 .mul => if (self.hasFeature(.avx)) .vmulpd else .mulpd,
6621 .add => if (self.hasFeature(.avx)) .{ ._, .vaddpd } else .{ ._, .addpd },
6622 .sub => if (self.hasFeature(.avx)) .{ ._, .vsubpd } else .{ ._, .subpd },
6623 .mul => if (self.hasFeature(.avx)) .{ ._, .vmulpd } else .{ ._, .mulpd },
65096624 .div_float,
65106625 .div_trunc,
65116626 .div_floor,
65126627 .div_exact,
6513 => if (self.hasFeature(.avx)) .vdivpd else .divpd,
6514 .max => if (self.hasFeature(.avx)) .vmaxpd else .maxpd,
6515 .min => if (self.hasFeature(.avx)) .vminpd else .minpd,
6628 => if (self.hasFeature(.avx)) .{ ._, .vdivpd } else .{ ._, .divpd },
6629 .max => if (self.hasFeature(.avx)) .{ ._, .vmaxpd } else .{ ._, .maxpd },
6630 .min => if (self.hasFeature(.avx)) .{ ._, .vminpd } else .{ ._, .minpd },
65166631 else => unreachable,
65176632 },
65186633 3...4 => if (self.hasFeature(.avx)) switch (air_tag) {
6519 .add => .vaddpd,
6520 .sub => .vsubpd,
6521 .mul => .vmulpd,
6522 .div_float, .div_trunc, .div_floor, .div_exact => .vdivpd,
6523 .max => .vmaxpd,
6524 .min => .vminpd,
6634 .add => .{ ._, .vaddpd },
6635 .sub => .{ ._, .vsubpd },
6636 .mul => .{ ._, .vmulpd },
6637 .div_float, .div_trunc, .div_floor, .div_exact => .{ ._, .vdivpd },
6638 .max => .{ ._, .vmaxpd },
6639 .min => .{ ._, .vminpd },
65256640 else => unreachable,
65266641 } else null,
65276642 else => null,
......@@ -6583,7 +6698,13 @@ fn genBinOp(
65836698 return dst_mcv;
65846699}
65856700
6586fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
6701fn genBinOpMir(
6702 self: *Self,
6703 mir_tag: Mir.Inst.FixedTag,
6704 ty: Type,
6705 dst_mcv: MCValue,
6706 src_mcv: MCValue,
6707) !void {
65876708 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
65886709 switch (dst_mcv) {
65896710 .none,
......@@ -6788,14 +6909,14 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
67886909 };
67896910 var off: i32 = 0;
67906911 while (off < abi_size) : (off += 8) {
6791 const mir_limb_tag = switch (off) {
6912 const mir_limb_tag: Mir.Inst.FixedTag = switch (off) {
67926913 0 => mir_tag,
6793 else => switch (mir_tag) {
6794 .add => .adc,
6795 .sub, .cmp => .sbb,
6914 else => switch (mir_tag[1]) {
6915 .add => .{ ._, .adc },
6916 .sub, .cmp => .{ ._, .sbb },
67966917 .@"or", .@"and", .xor => mir_tag,
67976918 else => return self.fail("TODO genBinOpMir implement large ABI for {s}", .{
6798 @tagName(mir_tag),
6919 @tagName(mir_tag[1]),
67996920 }),
68006921 },
68016922 };
......@@ -6967,14 +7088,14 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
69677088 .reserved_frame,
69687089 => unreachable,
69697090 .register => |src_reg| try self.asmRegisterRegister(
6970 .imul,
7091 .{ .i_, .mul },
69717092 dst_alias,
69727093 registerAlias(src_reg, abi_size),
69737094 ),
69747095 .immediate => |imm| {
69757096 if (math.cast(i32, imm)) |small| {
69767097 try self.asmRegisterRegisterImmediate(
6977 .imul,
7098 .{ .i_, .mul },
69787099 dst_alias,
69797100 dst_alias,
69807101 Immediate.s(small),
......@@ -6994,19 +7115,19 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
69947115 .lea_tlv,
69957116 .lea_frame,
69967117 => try self.asmRegisterRegister(
6997 .imul,
7118 .{ .i_, .mul },
69987119 dst_alias,
69997120 registerAlias(try self.copyToTmpRegister(dst_ty, src_mcv), abi_size),
70007121 ),
70017122 .memory, .indirect, .load_frame => try self.asmRegisterMemory(
7002 .imul,
7123 .{ .i_, .mul },
70037124 dst_alias,
70047125 Memory.sib(Memory.PtrSize.fromSize(abi_size), switch (src_mcv) {
70057126 .memory => |addr| .{
70067127 .base = .{ .reg = .ds },
70077128 .disp = math.cast(i32, @bitCast(i64, addr)) orelse
70087129 return self.asmRegisterRegister(
7009 .imul,
7130 .{ .i_, .mul },
70107131 dst_alias,
70117132 registerAlias(try self.copyToTmpRegister(dst_ty, src_mcv), abi_size),
70127133 ),
......@@ -7131,12 +7252,12 @@ fn genVarDbgInfo(
71317252}
71327253
71337254fn airTrap(self: *Self) !void {
7134 try self.asmOpOnly(.ud2);
7255 try self.asmOpOnly(.{ ._, .ud2 });
71357256 return self.finishAirBookkeeping();
71367257}
71377258
71387259fn airBreakpoint(self: *Self) !void {
7139 try self.asmOpOnly(.int3);
7260 try self.asmOpOnly(.{ ._, .int3 });
71407261 return self.finishAirBookkeeping();
71417262}
71427263
......@@ -7157,7 +7278,7 @@ fn airFence(self: *Self, inst: Air.Inst.Index) !void {
71577278 switch (order) {
71587279 .Unordered, .Monotonic => unreachable,
71597280 .Acquire, .Release, .AcqRel => {},
7160 .SeqCst => try self.asmOpOnly(.mfence),
7281 .SeqCst => try self.asmOpOnly(.{ ._, .mfence }),
71617282 }
71627283 return self.finishAirBookkeeping();
71637284}
......@@ -7251,7 +7372,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
72517372 const atom = elf_file.getAtom(atom_index);
72527373 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
72537374 const got_addr = atom.getOffsetTableAddress(elf_file);
7254 try self.asmMemory(.call, Memory.sib(.qword, .{
7375 try self.asmMemory(.{ ._, .call }, Memory.sib(.qword, .{
72557376 .base = .{ .reg = .ds },
72567377 .disp = @intCast(i32, got_addr),
72577378 }));
......@@ -7259,12 +7380,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
72597380 const atom = try coff_file.getOrCreateAtomForDecl(func.owner_decl);
72607381 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
72617382 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
7262 try self.asmRegister(.call, .rax);
7383 try self.asmRegister(.{ ._, .call }, .rax);
72637384 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
72647385 const atom = try macho_file.getOrCreateAtomForDecl(func.owner_decl);
72657386 const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;
72667387 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
7267 try self.asmRegister(.call, .rax);
7388 try self.asmRegister(.{ ._, .call }, .rax);
72687389 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
72697390 const decl_block_index = try p9.seeDecl(func.owner_decl);
72707391 const decl_block = p9.getDeclBlock(decl_block_index);
......@@ -7273,7 +7394,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
72737394 const got_addr = p9.bases.data;
72747395 const got_index = decl_block.got_index.?;
72757396 const fn_got_addr = got_addr + got_index * ptr_bytes;
7276 try self.asmMemory(.call, Memory.sib(.qword, .{
7397 try self.asmMemory(.{ ._, .call }, Memory.sib(.qword, .{
72777398 .base = .{ .reg = .ds },
72787399 .disp = @intCast(i32, fn_got_addr),
72797400 }));
......@@ -7296,7 +7417,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
72967417 }),
72977418 } },
72987419 });
7299 try self.asmRegister(.call, .rax);
7420 try self.asmRegister(.{ ._, .call }, .rax);
73007421 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
73017422 const atom_index = try self.owner.getSymbolIndex(self);
73027423 const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name);
......@@ -7318,7 +7439,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
73187439 assert(ty.zigTypeTag() == .Pointer);
73197440 const mcv = try self.resolveInst(callee);
73207441 try self.genSetReg(.rax, Type.usize, mcv);
7321 try self.asmRegister(.call, .rax);
7442 try self.asmRegister(.{ ._, .call }, .rax);
73227443 }
73237444
73247445 var bt = self.liveness.iterateBigTomb(inst);
......@@ -7408,7 +7529,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
74087529 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
74097530 const src_mcv = if (flipped) lhs_mcv else rhs_mcv;
74107531
7411 try self.genBinOpMir(.cmp, ty, dst_mcv, src_mcv);
7532 try self.genBinOpMir(.{ ._, .cmp }, ty, dst_mcv, src_mcv);
74127533 break :result Condition.fromCompareOperator(
74137534 if (ty.isAbiInt()) ty.intInfo(self.target.*).signedness else .unsigned,
74147535 if (flipped) op.reverse() else op,
......@@ -7442,13 +7563,13 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
74427563 defer self.register_manager.unlockReg(tmp2_lock);
74437564
74447565 if (src_mcv.isMemory()) try self.asmRegisterRegisterMemoryImmediate(
7445 .vpinsrw,
7566 .{ ._, .vpinsrw },
74467567 tmp1_reg,
74477568 dst_reg.to128(),
74487569 src_mcv.mem(.word),
74497570 Immediate.u(1),
74507571 ) else try self.asmRegisterRegisterRegister(
7451 .vpunpcklwd,
7572 .{ ._, .vpunpcklwd },
74527573 tmp1_reg,
74537574 dst_reg.to128(),
74547575 (if (src_mcv.isRegister())
......@@ -7456,14 +7577,24 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
74567577 else
74577578 try self.copyToTmpRegister(ty, src_mcv)).to128(),
74587579 );
7459 try self.asmRegisterRegister(.vcvtph2ps, tmp1_reg, tmp1_reg);
7460 try self.asmRegisterRegister(.vmovshdup, tmp2_reg, tmp1_reg);
7461 try self.genBinOpMir(.ucomiss, ty, tmp1_mcv, tmp2_mcv);
7580 try self.asmRegisterRegister(.{ ._, .vcvtph2ps }, tmp1_reg, tmp1_reg);
7581 try self.asmRegisterRegister(.{ ._, .vmovshdup }, tmp2_reg, tmp1_reg);
7582 try self.genBinOpMir(.{ ._, .ucomiss }, ty, tmp1_mcv, tmp2_mcv);
74627583 } else return self.fail("TODO implement airCmp for {}", .{
74637584 ty.fmt(self.bin_file.options.module.?),
74647585 }),
7465 32 => try self.genBinOpMir(.ucomiss, ty, .{ .register = dst_reg }, src_mcv),
7466 64 => try self.genBinOpMir(.ucomisd, ty, .{ .register = dst_reg }, src_mcv),
7586 32 => try self.genBinOpMir(
7587 .{ ._, .ucomiss },
7588 ty,
7589 .{ .register = dst_reg },
7590 src_mcv,
7591 ),
7592 64 => try self.genBinOpMir(
7593 .{ ._, .ucomisd },
7594 ty,
7595 .{ .register = dst_reg },
7596 src_mcv,
7597 ),
74677598 else => return self.fail("TODO implement airCmp for {}", .{
74687599 ty.fmt(self.bin_file.options.module.?),
74697600 }),
......@@ -7507,7 +7638,7 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {
75077638 else => try self.copyToTmpRegister(op_ty, op_mcv),
75087639 };
75097640 try self.asmRegisterMemory(
7510 .cmp,
7641 .{ ._, .cmp },
75117642 registerAlias(dst_reg, op_abi_size),
75127643 Memory.sib(Memory.PtrSize.fromSize(op_abi_size), .{ .base = .{ .reg = addr_reg } }),
75137644 );
......@@ -7627,7 +7758,7 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 {
76277758 },
76287759 .register => |reg| {
76297760 try self.spillEflagsIfOccupied();
7630 try self.asmRegisterImmediate(.@"test", reg, Immediate.u(1));
7761 try self.asmRegisterImmediate(.{ ._, .@"test" }, reg, Immediate.u(1));
76317762 return self.asmJccReloc(undefined, .e);
76327763 },
76337764 .immediate,
......@@ -7730,13 +7861,13 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
77307861 const some_abi_size = @intCast(u32, some_info.ty.abiSize(self.target.*));
77317862 const alias_reg = registerAlias(opt_reg, some_abi_size);
77327863 assert(some_abi_size * 8 == alias_reg.bitSize());
7733 try self.asmRegisterRegister(.@"test", alias_reg, alias_reg);
7864 try self.asmRegisterRegister(.{ ._, .@"test" }, alias_reg, alias_reg);
77347865 return .{ .eflags = .z };
77357866 }
77367867 assert(some_info.ty.tag() == .bool);
77377868 const opt_abi_size = @intCast(u32, opt_ty.abiSize(self.target.*));
77387869 try self.asmRegisterImmediate(
7739 .bt,
7870 .{ ._, .bt },
77407871 registerAlias(opt_reg, opt_abi_size),
77417872 Immediate.u(@intCast(u6, some_info.off * 8)),
77427873 );
......@@ -7755,7 +7886,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
77557886 try self.genSetReg(addr_reg, Type.usize, opt_mcv.address());
77567887 const some_abi_size = @intCast(u32, some_info.ty.abiSize(self.target.*));
77577888 try self.asmMemoryImmediate(
7758 .cmp,
7889 .{ ._, .cmp },
77597890 Memory.sib(Memory.PtrSize.fromSize(some_abi_size), .{
77607891 .base = .{ .reg = addr_reg },
77617892 .disp = some_info.off,
......@@ -7768,7 +7899,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
77687899 .indirect, .load_frame => {
77697900 const some_abi_size = @intCast(u32, some_info.ty.abiSize(self.target.*));
77707901 try self.asmMemoryImmediate(
7771 .cmp,
7902 .{ ._, .cmp },
77727903 Memory.sib(Memory.PtrSize.fromSize(some_abi_size), switch (opt_mcv) {
77737904 .indirect => |reg_off| .{
77747905 .base = .{ .reg = reg_off.reg },
......@@ -7810,7 +7941,7 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue)
78107941
78117942 const some_abi_size = @intCast(u32, some_info.ty.abiSize(self.target.*));
78127943 try self.asmMemoryImmediate(
7813 .cmp,
7944 .{ ._, .cmp },
78147945 Memory.sib(Memory.PtrSize.fromSize(some_abi_size), .{
78157946 .base = .{ .reg = ptr_reg },
78167947 .disp = some_info.off,
......@@ -7841,14 +7972,24 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !
78417972 const tmp_reg = try self.copyToTmpRegister(ty, operand);
78427973 if (err_off > 0) {
78437974 const shift = @intCast(u6, err_off * 8);
7844 try self.genShiftBinOpMir(.shr, ty, .{ .register = tmp_reg }, .{ .immediate = shift });
7975 try self.genShiftBinOpMir(
7976 .{ ._r, .sh },
7977 ty,
7978 .{ .register = tmp_reg },
7979 .{ .immediate = shift },
7980 );
78457981 } else {
78467982 try self.truncateRegister(Type.anyerror, tmp_reg);
78477983 }
7848 try self.genBinOpMir(.cmp, Type.anyerror, .{ .register = tmp_reg }, .{ .immediate = 0 });
7984 try self.genBinOpMir(
7985 .{ ._, .cmp },
7986 Type.anyerror,
7987 .{ .register = tmp_reg },
7988 .{ .immediate = 0 },
7989 );
78497990 },
78507991 .load_frame => |frame_addr| try self.genBinOpMir(
7851 .cmp,
7992 .{ ._, .cmp },
78527993 Type.anyerror,
78537994 .{ .load_frame = .{
78547995 .index = frame_addr.index,
......@@ -8073,7 +8214,7 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void {
80738214 try self.spillEflagsIfOccupied();
80748215 for (items, relocs, 0..) |item, *reloc, i| {
80758216 const item_mcv = try self.resolveInst(item);
8076 try self.genBinOpMir(.cmp, condition_ty, condition, item_mcv);
8217 try self.genBinOpMir(.{ ._, .cmp }, condition_ty, condition, item_mcv);
80778218 reloc.* = try self.asmJccReloc(undefined, if (i < relocs.len - 1) .e else .ne);
80788219 }
80798220
......@@ -8284,7 +8425,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
82848425 .qword
82858426 else
82868427 null;
8287 const mnem = mnem: {
8428 const mnem_tag = Mir.Inst.FixedTag{ ._, mnem: {
82888429 if (mnem_size) |_| {
82898430 if (std.meta.stringToEnum(Mir.Inst.Tag, mnem_str[0 .. mnem_str.len - 1])) |mnem| {
82908431 break :mnem mnem;
......@@ -8292,7 +8433,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
82928433 }
82938434 break :mnem std.meta.stringToEnum(Mir.Inst.Tag, mnem_str) orelse
82948435 return self.fail("Invalid mnemonic: '{s}'", .{mnem_str});
8295 };
8436 } };
82968437
82978438 var op_it = mem.tokenize(u8, mnem_it.rest(), ",");
82988439 var ops = [1]encoder.Instruction.Operand{.none} ** 4;
......@@ -8343,51 +8484,51 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
83438484 } else if (op_it.next()) |op_str| return self.fail("Extra operand: '{s}'", .{op_str});
83448485
83458486 (switch (ops[0]) {
8346 .none => self.asmOpOnly(mnem),
8487 .none => self.asmOpOnly(mnem_tag),
83478488 .reg => |reg0| switch (ops[1]) {
8348 .none => self.asmRegister(mnem, reg0),
8489 .none => self.asmRegister(mnem_tag, reg0),
83498490 .reg => |reg1| switch (ops[2]) {
8350 .none => self.asmRegisterRegister(mnem, reg1, reg0),
8491 .none => self.asmRegisterRegister(mnem_tag, reg1, reg0),
83518492 .reg => |reg2| switch (ops[3]) {
8352 .none => self.asmRegisterRegisterRegister(mnem, reg2, reg1, reg0),
8493 .none => self.asmRegisterRegisterRegister(mnem_tag, reg2, reg1, reg0),
83538494 else => error.InvalidInstruction,
83548495 },
83558496 .mem => |mem2| switch (ops[3]) {
8356 .none => self.asmMemoryRegisterRegister(mnem, mem2, reg1, reg0),
8497 .none => self.asmMemoryRegisterRegister(mnem_tag, mem2, reg1, reg0),
83578498 else => error.InvalidInstruction,
83588499 },
83598500 else => error.InvalidInstruction,
83608501 },
83618502 .mem => |mem1| switch (ops[2]) {
8362 .none => self.asmMemoryRegister(mnem, mem1, reg0),
8503 .none => self.asmMemoryRegister(mnem_tag, mem1, reg0),
83638504 else => error.InvalidInstruction,
83648505 },
83658506 else => error.InvalidInstruction,
83668507 },
83678508 .mem => |mem0| switch (ops[1]) {
8368 .none => self.asmMemory(mnem, mem0),
8509 .none => self.asmMemory(mnem_tag, mem0),
83698510 .reg => |reg1| switch (ops[2]) {
8370 .none => self.asmRegisterMemory(mnem, reg1, mem0),
8511 .none => self.asmRegisterMemory(mnem_tag, reg1, mem0),
83718512 else => error.InvalidInstruction,
83728513 },
83738514 else => error.InvalidInstruction,
83748515 },
83758516 .imm => |imm0| switch (ops[1]) {
8376 .none => self.asmImmediate(mnem, imm0),
8517 .none => self.asmImmediate(mnem_tag, imm0),
83778518 .reg => |reg1| switch (ops[2]) {
8378 .none => self.asmRegisterImmediate(mnem, reg1, imm0),
8519 .none => self.asmRegisterImmediate(mnem_tag, reg1, imm0),
83798520 .reg => |reg2| switch (ops[3]) {
8380 .none => self.asmRegisterRegisterImmediate(mnem, reg2, reg1, imm0),
8521 .none => self.asmRegisterRegisterImmediate(mnem_tag, reg2, reg1, imm0),
83818522 else => error.InvalidInstruction,
83828523 },
83838524 .mem => |mem2| switch (ops[3]) {
8384 .none => self.asmMemoryRegisterImmediate(mnem, mem2, reg1, imm0),
8525 .none => self.asmMemoryRegisterImmediate(mnem_tag, mem2, reg1, imm0),
83858526 else => error.InvalidInstruction,
83868527 },
83878528 else => error.InvalidInstruction,
83888529 },
83898530 .mem => |mem1| switch (ops[2]) {
8390 .none => self.asmMemoryImmediate(mnem, mem1, imm0),
8531 .none => self.asmMemoryImmediate(mnem_tag, mem1, imm0),
83918532 else => error.InvalidInstruction,
83928533 },
83938534 else => error.InvalidInstruction,
......@@ -8396,7 +8537,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
83968537 error.InvalidInstruction => return self.fail(
83978538 "Invalid instruction: '{s} {s} {s} {s} {s}'",
83988539 .{
8399 @tagName(mnem),
8540 @tagName(mnem_tag[1]),
84008541 @tagName(ops[0]),
84018542 @tagName(ops[1]),
84028543 @tagName(ops[2]),
......@@ -8427,44 +8568,47 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
84278568 return self.finishAirResult(inst, result);
84288569}
84298570
8430fn movMirTag(self: *Self, ty: Type, aligned: bool) !Mir.Inst.Tag {
8571fn movMirTag(self: *Self, ty: Type, aligned: bool) !Mir.Inst.FixedTag {
84318572 switch (ty.zigTypeTag()) {
8432 else => return .mov,
8573 else => return .{ ._, .mov },
84338574 .Float => switch (ty.floatBits(self.target.*)) {
84348575 16 => unreachable, // needs special handling
8435 32 => return if (self.hasFeature(.avx)) .vmovss else .movss,
8436 64 => return if (self.hasFeature(.avx)) .vmovsd else .movsd,
8576 32 => return if (self.hasFeature(.avx)) .{ ._, .vmovss } else .{ ._, .movss },
8577 64 => return if (self.hasFeature(.avx)) .{ ._, .vmovsd } else .{ ._, .movsd },
84378578 128 => return if (self.hasFeature(.avx))
8438 if (aligned) .vmovaps else .vmovups
8439 else if (aligned) .movaps else .movups,
8579 if (aligned) .{ ._, .vmovaps } else .{ ._, .vmovups }
8580 else if (aligned) .{ ._, .movaps } else .{ ._, .movups },
84408581 else => {},
84418582 },
84428583 .Vector => switch (ty.childType().zigTypeTag()) {
84438584 .Float => switch (ty.childType().floatBits(self.target.*)) {
84448585 16 => switch (ty.vectorLen()) {
84458586 1 => unreachable, // needs special handling
8446 2 => return if (self.hasFeature(.avx)) .vmovss else .movss,
8447 3...4 => return if (self.hasFeature(.avx)) .vmovsd else .movsd,
8587 2 => return if (self.hasFeature(.avx)) .{ ._, .vmovss } else .{ ._, .movss },
8588 3...4 => return if (self.hasFeature(.avx)) .{ ._, .vmovsd } else .{ ._, .movsd },
84488589 5...8 => return if (self.hasFeature(.avx))
8449 if (aligned) .vmovaps else .vmovups
8450 else if (aligned) .movaps else .movups,
8451 9...16 => if (self.hasFeature(.avx)) return if (aligned) .vmovaps else .vmovups,
8590 if (aligned) .{ ._, .vmovaps } else .{ ._, .vmovups }
8591 else if (aligned) .{ ._, .movaps } else .{ ._, .movups },
8592 9...16 => if (self.hasFeature(.avx))
8593 return if (aligned) .{ ._, .vmovaps } else .{ ._, .vmovups },
84528594 else => {},
84538595 },
84548596 32 => switch (ty.vectorLen()) {
8455 1 => return if (self.hasFeature(.avx)) .vmovss else .movss,
8597 1 => return if (self.hasFeature(.avx)) .{ ._, .vmovss } else .{ ._, .movss },
84568598 2...4 => return if (self.hasFeature(.avx))
8457 if (aligned) .vmovaps else .vmovups
8458 else if (aligned) .movaps else .movups,
8459 5...8 => if (self.hasFeature(.avx)) return if (aligned) .vmovaps else .vmovups,
8599 if (aligned) .{ ._, .vmovaps } else .{ ._, .vmovups }
8600 else if (aligned) .{ ._, .movaps } else .{ ._, .movups },
8601 5...8 => if (self.hasFeature(.avx))
8602 return if (aligned) .{ ._, .vmovaps } else .{ ._, .vmovups },
84608603 else => {},
84618604 },
84628605 64 => switch (ty.vectorLen()) {
8463 1 => return if (self.hasFeature(.avx)) .vmovsd else .movsd,
8606 1 => return if (self.hasFeature(.avx)) .{ ._, .vmovsd } else .{ ._, .movsd },
84648607 2 => return if (self.hasFeature(.avx))
8465 if (aligned) .vmovaps else .vmovups
8466 else if (aligned) .movaps else .movups,
8467 3...4 => if (self.hasFeature(.avx)) return if (aligned) .vmovaps else .vmovups,
8608 if (aligned) .{ ._, .vmovaps } else .{ ._, .vmovups }
8609 else if (aligned) .{ ._, .movaps } else .{ ._, .movups },
8610 3...4 => if (self.hasFeature(.avx))
8611 return if (aligned) .{ ._, .vmovaps } else .{ ._, .vmovups },
84688612 else => {},
84698613 },
84708614 else => {},
......@@ -8558,19 +8702,19 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
85588702 if (imm == 0) {
85598703 // 32-bit moves zero-extend to 64-bit, so xoring the 32-bit
85608704 // register is the fastest way to zero a register.
8561 try self.asmRegisterRegister(.xor, dst_reg.to32(), dst_reg.to32());
8705 try self.asmRegisterRegister(.{ ._, .xor }, dst_reg.to32(), dst_reg.to32());
85628706 } else if (abi_size > 4 and math.cast(u32, imm) != null) {
85638707 // 32-bit moves zero-extend to 64-bit.
8564 try self.asmRegisterImmediate(.mov, dst_reg.to32(), Immediate.u(imm));
8708 try self.asmRegisterImmediate(.{ ._, .mov }, dst_reg.to32(), Immediate.u(imm));
85658709 } else if (abi_size <= 4 and @bitCast(i64, imm) < 0) {
85668710 try self.asmRegisterImmediate(
8567 .mov,
8711 .{ ._, .mov },
85688712 registerAlias(dst_reg, abi_size),
85698713 Immediate.s(@intCast(i32, @bitCast(i64, imm))),
85708714 );
85718715 } else {
85728716 try self.asmRegisterImmediate(
8573 .mov,
8717 .{ ._, .mov },
85748718 registerAlias(dst_reg, abi_size),
85758719 Immediate.u(imm),
85768720 );
......@@ -8579,18 +8723,18 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
85798723 .register => |src_reg| if (dst_reg.id() != src_reg.id()) try self.asmRegisterRegister(
85808724 if ((dst_reg.class() == .floating_point) == (src_reg.class() == .floating_point))
85818725 switch (ty.zigTypeTag()) {
8582 else => .mov,
8583 .Float, .Vector => .movaps,
8726 else => .{ ._, .mov },
8727 .Float, .Vector => .{ ._, .movaps },
85848728 }
85858729 else switch (abi_size) {
85868730 2 => return try self.asmRegisterRegisterImmediate(
8587 if (dst_reg.class() == .floating_point) .pinsrw else .pextrw,
8731 if (dst_reg.class() == .floating_point) .{ ._, .pinsrw } else .{ ._, .pextrw },
85888732 registerAlias(dst_reg, 4),
85898733 registerAlias(src_reg, 4),
85908734 Immediate.u(0),
85918735 ),
8592 4 => .movd,
8593 8 => .movq,
8736 4 => .{ ._d, .mov },
8737 8 => .{ ._q, .mov },
85948738 else => return self.fail(
85958739 "unsupported register copy from {s} to {s}",
85968740 .{ @tagName(src_reg), @tagName(dst_reg) },
......@@ -8617,7 +8761,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
86178761 });
86188762 if (ty.isRuntimeFloat() and ty.floatBits(self.target.*) == 16)
86198763 try self.asmRegisterMemoryImmediate(
8620 .pinsrw,
8764 .{ ._, .pinsrw },
86218765 registerAlias(dst_reg, abi_size),
86228766 src_mem,
86238767 Immediate.u(0),
......@@ -8627,14 +8771,14 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
86278771 switch (src_mcv) {
86288772 .register_offset => |reg_off| switch (reg_off.off) {
86298773 0 => return self.genSetReg(dst_reg, ty, .{ .register = reg_off.reg }),
8630 else => .lea,
8774 else => .{ ._, .lea },
86318775 },
86328776 .indirect => try self.movMirTag(ty, false),
86338777 .load_frame => |frame_addr| try self.movMirTag(
86348778 ty,
86358779 self.getFrameAddrAlignment(frame_addr) >= ty.abiAlignment(self.target.*),
86368780 ),
8637 .lea_frame => .lea,
8781 .lea_frame => .{ ._, .lea },
86388782 else => unreachable,
86398783 },
86408784 registerAlias(dst_reg, abi_size),
......@@ -8650,7 +8794,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
86508794 });
86518795 return if (ty.isRuntimeFloat() and ty.floatBits(self.target.*) == 16)
86528796 self.asmRegisterMemoryImmediate(
8653 .pinsrw,
8797 .{ ._, .pinsrw },
86548798 registerAlias(dst_reg, abi_size),
86558799 src_mem,
86568800 Immediate.u(0),
......@@ -8694,7 +8838,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
86948838 });
86958839 if (ty.isRuntimeFloat() and ty.floatBits(self.target.*) == 16)
86968840 try self.asmRegisterMemoryImmediate(
8697 .pinsrw,
8841 .{ ._, .pinsrw },
86988842 registerAlias(dst_reg, abi_size),
86998843 src_mem,
87008844 Immediate.u(0),
......@@ -8743,7 +8887,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
87438887 } },
87448888 });
87458889 // TODO: spill registers before calling
8746 try self.asmMemory(.call, Memory.sib(.qword, .{ .base = .{ .reg = .rdi } }));
8890 try self.asmMemory(.{ ._, .call }, Memory.sib(.qword, .{ .base = .{ .reg = .rdi } }));
87478891 try self.genSetReg(dst_reg.to64(), Type.usize, .{ .register = .rax });
87488892 } else return self.fail("TODO emit ptr to TLV sequence on {s}", .{
87498893 @tagName(self.bin_file.tag),
......@@ -8770,7 +8914,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
87708914 else
87718915 Immediate.u(@intCast(u32, imm));
87728916 try self.asmMemoryImmediate(
8773 .mov,
8917 .{ ._, .mov },
87748918 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base, .disp = disp }),
87758919 immediate,
87768920 );
......@@ -8778,14 +8922,14 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
87788922 3, 5...7 => unreachable,
87798923 else => if (math.cast(i32, @bitCast(i64, imm))) |small| {
87808924 try self.asmMemoryImmediate(
8781 .mov,
8925 .{ ._, .mov },
87828926 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = base, .disp = disp }),
87838927 Immediate.s(small),
87848928 );
87858929 } else {
87868930 var offset: i32 = 0;
87878931 while (offset < abi_size) : (offset += 4) try self.asmMemoryImmediate(
8788 .mov,
8932 .{ ._, .mov },
87898933 Memory.sib(.dword, .{ .base = base, .disp = disp + offset }),
87908934 if (ty.isSignedInt())
87918935 Immediate.s(@truncate(
......@@ -8808,7 +8952,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
88088952 );
88098953 if (ty.isRuntimeFloat() and ty.floatBits(self.target.*) == 16)
88108954 try self.asmMemoryRegisterImmediate(
8811 .pextrw,
8955 .{ ._, .pextrw },
88128956 dst_mem,
88138957 src_reg.to128(),
88148958 Immediate.u(0),
......@@ -8904,7 +9048,7 @@ fn genInlineMemcpyRegisterRegister(
89049048 while (remainder > 0) {
89059049 const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder));
89069050 try self.asmMemoryRegister(
8907 .mov,
9051 .{ ._, .mov },
89089052 Memory.sib(Memory.PtrSize.fromSize(nearest_power_of_two), .{
89099053 .base = dst_reg,
89109054 .disp = -next_offset,
......@@ -8913,7 +9057,7 @@ fn genInlineMemcpyRegisterRegister(
89139057 );
89149058
89159059 if (nearest_power_of_two > 1) {
8916 try self.genShiftBinOpMir(.shr, ty, .{ .register = tmp_reg }, .{
9060 try self.genShiftBinOpMir(.{ ._r, .sh }, ty, .{ .register = tmp_reg }, .{
89179061 .immediate = nearest_power_of_two * 8,
89189062 });
89199063 }
......@@ -8924,8 +9068,8 @@ fn genInlineMemcpyRegisterRegister(
89249068 } else {
89259069 try self.asmMemoryRegister(
89269070 switch (src_reg.class()) {
8927 .general_purpose, .segment => .mov,
8928 .floating_point => .movss,
9071 .general_purpose, .segment => .{ ._, .mov },
9072 .floating_point => .{ ._, .movss },
89299073 },
89309074 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = dst_reg, .disp = -offset }),
89319075 registerAlias(src_reg, abi_size),
......@@ -8938,11 +9082,7 @@ fn genInlineMemcpy(self: *Self, dst_ptr: MCValue, src_ptr: MCValue, len: MCValue
89389082 try self.genSetReg(.rdi, Type.usize, dst_ptr);
89399083 try self.genSetReg(.rsi, Type.usize, src_ptr);
89409084 try self.genSetReg(.rcx, Type.usize, len);
8941 _ = try self.addInst(.{
8942 .tag = .mov,
8943 .ops = .none,
8944 .data = .{ .none = .{ .fixes = .@"rep _sb" } },
8945 });
9085 try self.asmOpOnly(.{ .@"rep _sb", .mov });
89469086}
89479087
89489088fn genInlineMemset(self: *Self, dst_ptr: MCValue, value: MCValue, len: MCValue) InnerError!void {
......@@ -8950,11 +9090,7 @@ fn genInlineMemset(self: *Self, dst_ptr: MCValue, value: MCValue, len: MCValue)
89509090 try self.genSetReg(.rdi, Type.usize, dst_ptr);
89519091 try self.genSetReg(.al, Type.u8, value);
89529092 try self.genSetReg(.rcx, Type.usize, len);
8953 _ = try self.addInst(.{
8954 .tag = .sto,
8955 .ops = .none,
8956 .data = .{ .none = .{ .fixes = .@"rep _sb" } },
8957 });
9093 try self.asmOpOnly(.{ .@"rep _sb", .sto });
89589094}
89599095
89609096fn genLazySymbolRef(
......@@ -8972,14 +9108,14 @@ fn genLazySymbolRef(
89729108 const got_mem =
89739109 Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) });
89749110 switch (tag) {
8975 .lea, .mov => try self.asmRegisterMemory(.mov, reg.to64(), got_mem),
8976 .call => try self.asmMemory(.call, got_mem),
9111 .lea, .mov => try self.asmRegisterMemory(.{ ._, .mov }, reg.to64(), got_mem),
9112 .call => try self.asmMemory(.{ ._, .call }, got_mem),
89779113 else => unreachable,
89789114 }
89799115 switch (tag) {
89809116 .lea, .call => {},
89819117 .mov => try self.asmRegisterMemory(
8982 tag,
9118 .{ ._, tag },
89839119 reg.to64(),
89849120 Memory.sib(.qword, .{ .base = .{ .reg = reg.to64() } }),
89859121 ),
......@@ -8996,7 +9132,7 @@ fn genLazySymbolRef(
89969132 }
89979133 switch (tag) {
89989134 .lea, .mov => {},
8999 .call => try self.asmRegister(.call, reg),
9135 .call => try self.asmRegister(.{ ._, .call }, reg),
90009136 else => unreachable,
90019137 }
90029138 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
......@@ -9010,7 +9146,7 @@ fn genLazySymbolRef(
90109146 }
90119147 switch (tag) {
90129148 .lea, .mov => {},
9013 .call => try self.asmRegister(.call, reg),
9149 .call => try self.asmRegister(.{ ._, .call }, reg),
90149150 else => unreachable,
90159151 }
90169152 } else {
......@@ -9115,13 +9251,13 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
91159251
91169252 try self.asmRegisterRegister(switch (dst_ty.floatBits(self.target.*)) {
91179253 32 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse))
9118 .cvtsi2ss
9254 .{ ._, .cvtsi2ss }
91199255 else
91209256 return self.fail("TODO implement airIntToFloat from {} to {} without sse", .{
91219257 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
91229258 }),
91239259 64 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse2))
9124 .cvtsi2sd
9260 .{ ._, .cvtsi2sd }
91259261 else
91269262 return self.fail("TODO implement airIntToFloat from {} to {} without sse2", .{
91279263 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
......@@ -9161,7 +9297,7 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {
91619297 },
91629298 };
91639299 try self.asmMemory(
9164 .fld,
9300 .{ .f_, .ld },
91659301 Memory.sib(Memory.PtrSize.fromSize(src_abi_size), .{
91669302 .base = .{ .frame = frame_addr.index },
91679303 .disp = frame_addr.off,
......@@ -9171,7 +9307,7 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {
91719307 // convert
91729308 const stack_dst = try self.allocRegOrMem(inst, false);
91739309 try self.asmMemory(
9174 .fisttp,
9310 .{ .f_p, .istt },
91759311 Memory.sib(Memory.PtrSize.fromSize(dst_abi_size), .{
91769312 .base = .{ .frame = stack_dst.load_frame.index },
91779313 .disp = stack_dst.load_frame.off,
......@@ -9227,22 +9363,11 @@ fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {
92279363 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
92289364
92299365 try self.spillEflagsIfOccupied();
9230 _ = try self.addInst(if (val_abi_size <= 8) .{
9231 .tag = .cmpxchg,
9232 .ops = .mr_sib,
9233 .data = .{ .rx = .{
9234 .fixes = .@"lock _",
9235 .r1 = registerAlias(new_reg.?, val_abi_size),
9236 .payload = try self.addExtra(Mir.MemorySib.encode(ptr_mem)),
9237 } },
9238 } else .{
9239 .tag = .cmpxchg,
9240 .ops = .m_sib,
9241 .data = .{ .x = .{
9242 .fixes = .@"lock _16b",
9243 .payload = try self.addExtra(Mir.MemorySib.encode(ptr_mem)),
9244 } },
9245 });
9366 if (val_abi_size <= 8) try self.asmMemoryRegister(
9367 .{ .@"lock _", .cmpxchg },
9368 ptr_mem,
9369 registerAlias(new_reg.?, val_abi_size),
9370 ) else try self.asmMemory(.{ .@"lock _16b", .cmpxchg }, ptr_mem);
92469371
92479372 const result: MCValue = result: {
92489373 if (self.liveness.isUnused(inst)) break :result .unreach;
......@@ -9340,21 +9465,17 @@ fn atomicOp(
93409465
93419466 try self.genSetReg(dst_reg, val_ty, val_mcv);
93429467 if (rmw_op == std.builtin.AtomicRmwOp.Sub and tag == .xadd) {
9343 try self.genUnOpMir(.neg, val_ty, dst_mcv);
9468 try self.genUnOpMir(.{ ._, .neg }, val_ty, dst_mcv);
93449469 }
9345 _ = try self.addInst(.{
9346 .tag = tag,
9347 .ops = .mr_sib,
9348 .data = .{ .rx = .{
9349 .fixes = switch (tag) {
9350 .mov, .xchg => ._,
9351 .xadd, .add, .sub, .@"and", .@"or", .xor => .@"lock _",
9352 else => unreachable,
9353 },
9354 .r1 = registerAlias(dst_reg, val_abi_size),
9355 .payload = try self.addExtra(Mir.MemorySib.encode(ptr_mem)),
9356 } },
9357 });
9470 try self.asmMemoryRegister(
9471 switch (tag) {
9472 .mov, .xchg => .{ ._, tag },
9473 .xadd, .add, .sub, .@"and", .@"or", .xor => .{ .@"lock _", tag },
9474 else => unreachable,
9475 },
9476 ptr_mem,
9477 registerAlias(dst_reg, val_abi_size),
9478 );
93589479
93599480 return if (unused) .unreach else dst_mcv;
93609481 },
......@@ -9364,22 +9485,22 @@ fn atomicOp(
93649485 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
93659486 defer self.register_manager.unlockReg(tmp_lock);
93669487
9367 try self.asmRegisterMemory(.mov, registerAlias(.rax, val_abi_size), ptr_mem);
9488 try self.asmRegisterMemory(.{ ._, .mov }, registerAlias(.rax, val_abi_size), ptr_mem);
93689489 const loop = @intCast(u32, self.mir_instructions.len);
93699490 if (rmw_op != std.builtin.AtomicRmwOp.Xchg) {
93709491 try self.genSetReg(tmp_reg, val_ty, .{ .register = .rax });
93719492 }
93729493 if (rmw_op) |op| switch (op) {
93739494 .Xchg => try self.genSetReg(tmp_reg, val_ty, val_mcv),
9374 .Add => try self.genBinOpMir(.add, val_ty, tmp_mcv, val_mcv),
9375 .Sub => try self.genBinOpMir(.sub, val_ty, tmp_mcv, val_mcv),
9376 .And => try self.genBinOpMir(.@"and", val_ty, tmp_mcv, val_mcv),
9495 .Add => try self.genBinOpMir(.{ ._, .add }, val_ty, tmp_mcv, val_mcv),
9496 .Sub => try self.genBinOpMir(.{ ._, .sub }, val_ty, tmp_mcv, val_mcv),
9497 .And => try self.genBinOpMir(.{ ._, .@"and" }, val_ty, tmp_mcv, val_mcv),
93779498 .Nand => {
9378 try self.genBinOpMir(.@"and", val_ty, tmp_mcv, val_mcv);
9379 try self.genUnOpMir(.not, val_ty, tmp_mcv);
9499 try self.genBinOpMir(.{ ._, .@"and" }, val_ty, tmp_mcv, val_mcv);
9500 try self.genUnOpMir(.{ ._, .not }, val_ty, tmp_mcv);
93809501 },
9381 .Or => try self.genBinOpMir(.@"or", val_ty, tmp_mcv, val_mcv),
9382 .Xor => try self.genBinOpMir(.xor, val_ty, tmp_mcv, val_mcv),
9502 .Or => try self.genBinOpMir(.{ ._, .@"or" }, val_ty, tmp_mcv, val_mcv),
9503 .Xor => try self.genBinOpMir(.{ ._, .xor }, val_ty, tmp_mcv, val_mcv),
93839504 .Min, .Max => {
93849505 const cc: Condition = switch (if (val_ty.isAbiInt())
93859506 val_ty.intInfo(self.target.*).signedness
......@@ -9397,7 +9518,7 @@ fn atomicOp(
93979518 },
93989519 };
93999520
9400 try self.genBinOpMir(.cmp, val_ty, tmp_mcv, val_mcv);
9521 try self.genBinOpMir(.{ ._, .cmp }, val_ty, tmp_mcv, val_mcv);
94019522 const cmov_abi_size = @max(val_abi_size, 2);
94029523 switch (val_mcv) {
94039524 .register => |val_reg| try self.asmCmovccRegisterRegister(
......@@ -9421,24 +9542,20 @@ fn atomicOp(
94219542 }
94229543 },
94239544 };
9424 _ = try self.addInst(.{
9425 .tag = .cmpxchg,
9426 .ops = .mr_sib,
9427 .data = .{ .rx = .{
9428 .fixes = .@"lock _",
9429 .r1 = registerAlias(tmp_reg, val_abi_size),
9430 .payload = try self.addExtra(Mir.MemorySib.encode(ptr_mem)),
9431 } },
9432 });
9545 try self.asmMemoryRegister(
9546 .{ .@"lock _", .cmpxchg },
9547 ptr_mem,
9548 registerAlias(tmp_reg, val_abi_size),
9549 );
94339550 _ = try self.asmJccReloc(loop, .ne);
94349551 return if (unused) .unreach else .{ .register = .rax };
94359552 } else {
9436 try self.asmRegisterMemory(.mov, .rax, Memory.sib(.qword, .{
9553 try self.asmRegisterMemory(.{ ._, .mov }, .rax, Memory.sib(.qword, .{
94379554 .base = ptr_mem.sib.base,
94389555 .scale_index = ptr_mem.scaleIndex(),
94399556 .disp = ptr_mem.sib.disp + 0,
94409557 }));
9441 try self.asmRegisterMemory(.mov, .rdx, Memory.sib(.qword, .{
9558 try self.asmRegisterMemory(.{ ._, .mov }, .rdx, Memory.sib(.qword, .{
94429559 .base = ptr_mem.sib.base,
94439560 .scale_index = ptr_mem.scaleIndex(),
94449561 .disp = ptr_mem.sib.disp + 8,
......@@ -9453,58 +9570,51 @@ fn atomicOp(
94539570 const val_lo_mem = val_mem_mcv.mem(.qword);
94549571 const val_hi_mem = val_mem_mcv.address().offset(8).deref().mem(.qword);
94559572 if (rmw_op != std.builtin.AtomicRmwOp.Xchg) {
9456 try self.asmRegisterRegister(.mov, .rbx, .rax);
9457 try self.asmRegisterRegister(.mov, .rcx, .rdx);
9573 try self.asmRegisterRegister(.{ ._, .mov }, .rbx, .rax);
9574 try self.asmRegisterRegister(.{ ._, .mov }, .rcx, .rdx);
94589575 }
94599576 if (rmw_op) |op| switch (op) {
94609577 .Xchg => {
9461 try self.asmRegisterMemory(.mov, .rbx, val_lo_mem);
9462 try self.asmRegisterMemory(.mov, .rcx, val_hi_mem);
9578 try self.asmRegisterMemory(.{ ._, .mov }, .rbx, val_lo_mem);
9579 try self.asmRegisterMemory(.{ ._, .mov }, .rcx, val_hi_mem);
94639580 },
94649581 .Add => {
9465 try self.asmRegisterMemory(.add, .rbx, val_lo_mem);
9466 try self.asmRegisterMemory(.adc, .rcx, val_hi_mem);
9582 try self.asmRegisterMemory(.{ ._, .add }, .rbx, val_lo_mem);
9583 try self.asmRegisterMemory(.{ ._, .adc }, .rcx, val_hi_mem);
94679584 },
94689585 .Sub => {
9469 try self.asmRegisterMemory(.sub, .rbx, val_lo_mem);
9470 try self.asmRegisterMemory(.sbb, .rcx, val_hi_mem);
9586 try self.asmRegisterMemory(.{ ._, .sub }, .rbx, val_lo_mem);
9587 try self.asmRegisterMemory(.{ ._, .sbb }, .rcx, val_hi_mem);
94719588 },
94729589 .And => {
9473 try self.asmRegisterMemory(.@"and", .rbx, val_lo_mem);
9474 try self.asmRegisterMemory(.@"and", .rcx, val_hi_mem);
9590 try self.asmRegisterMemory(.{ ._, .@"and" }, .rbx, val_lo_mem);
9591 try self.asmRegisterMemory(.{ ._, .@"and" }, .rcx, val_hi_mem);
94759592 },
94769593 .Nand => {
9477 try self.asmRegisterMemory(.@"and", .rbx, val_lo_mem);
9478 try self.asmRegisterMemory(.@"and", .rcx, val_hi_mem);
9479 try self.asmRegister(.not, .rbx);
9480 try self.asmRegister(.not, .rcx);
9594 try self.asmRegisterMemory(.{ ._, .@"and" }, .rbx, val_lo_mem);
9595 try self.asmRegisterMemory(.{ ._, .@"and" }, .rcx, val_hi_mem);
9596 try self.asmRegister(.{ ._, .not }, .rbx);
9597 try self.asmRegister(.{ ._, .not }, .rcx);
94819598 },
94829599 .Or => {
9483 try self.asmRegisterMemory(.@"or", .rbx, val_lo_mem);
9484 try self.asmRegisterMemory(.@"or", .rcx, val_hi_mem);
9600 try self.asmRegisterMemory(.{ ._, .@"or" }, .rbx, val_lo_mem);
9601 try self.asmRegisterMemory(.{ ._, .@"or" }, .rcx, val_hi_mem);
94859602 },
94869603 .Xor => {
9487 try self.asmRegisterMemory(.xor, .rbx, val_lo_mem);
9488 try self.asmRegisterMemory(.xor, .rcx, val_hi_mem);
9604 try self.asmRegisterMemory(.{ ._, .xor }, .rbx, val_lo_mem);
9605 try self.asmRegisterMemory(.{ ._, .xor }, .rcx, val_hi_mem);
94899606 },
94909607 else => return self.fail("TODO implement x86 atomic loop for {} {s}", .{
94919608 val_ty.fmt(self.bin_file.options.module.?), @tagName(op),
94929609 }),
94939610 };
9494 _ = try self.addInst(.{
9495 .tag = .cmpxchg,
9496 .ops = .m_sib,
9497 .data = .{ .x = .{
9498 .fixes = .@"lock _16b",
9499 .payload = try self.addExtra(Mir.MemorySib.encode(ptr_mem)),
9500 } },
9501 });
9611 try self.asmMemory(.{ .@"lock _16b", .cmpxchg }, ptr_mem);
95029612 _ = try self.asmJccReloc(loop, .ne);
95039613
95049614 if (unused) return .unreach;
95059615 const dst_mcv = try self.allocTempRegOrMem(val_ty, false);
95069616 try self.asmMemoryRegister(
9507 .mov,
9617 .{ ._, .mov },
95089618 Memory.sib(.qword, .{
95099619 .base = .{ .frame = dst_mcv.load_frame.index },
95109620 .disp = dst_mcv.load_frame.off + 0,
......@@ -9512,7 +9622,7 @@ fn atomicOp(
95129622 .rax,
95139623 );
95149624 try self.asmMemoryRegister(
9515 .mov,
9625 .{ ._, .mov },
95169626 Memory.sib(.qword, .{
95179627 .base = .{ .frame = dst_mcv.load_frame.index },
95189628 .disp = dst_mcv.load_frame.off + 8,
......@@ -9664,8 +9774,13 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
96649774 .off = elem_abi_size,
96659775 } });
96669776
9667 try self.genBinOpMir(.sub, Type.usize, len_mcv, .{ .immediate = 1 });
9668 try self.asmRegisterRegisterImmediate(.imul, len_reg, len_reg, Immediate.u(elem_abi_size));
9777 try self.genBinOpMir(.{ ._, .sub }, Type.usize, len_mcv, .{ .immediate = 1 });
9778 try self.asmRegisterRegisterImmediate(
9779 .{ .i_, .mul },
9780 len_reg,
9781 len_reg,
9782 Immediate.u(elem_abi_size),
9783 );
96699784 try self.genInlineMemcpy(second_elem_ptr_mcv, ptr, len_mcv);
96709785
96719786 try self.performReloc(skip_reloc);
......@@ -9803,7 +9918,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
98039918 try self.truncateRegister(err_ty, err_reg.to32());
98049919
98059920 try self.asmRegisterMemory(
9806 .mov,
9921 .{ ._, .mov },
98079922 start_reg.to32(),
98089923 Memory.sib(.dword, .{
98099924 .base = .{ .reg = addr_reg.to64() },
......@@ -9812,7 +9927,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
98129927 }),
98139928 );
98149929 try self.asmRegisterMemory(
9815 .mov,
9930 .{ ._, .mov },
98169931 end_reg.to32(),
98179932 Memory.sib(.dword, .{
98189933 .base = .{ .reg = addr_reg.to64() },
......@@ -9820,9 +9935,9 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
98209935 .disp = 8,
98219936 }),
98229937 );
9823 try self.asmRegisterRegister(.sub, end_reg.to32(), start_reg.to32());
9938 try self.asmRegisterRegister(.{ ._, .sub }, end_reg.to32(), start_reg.to32());
98249939 try self.asmRegisterMemory(
9825 .lea,
9940 .{ ._, .lea },
98269941 start_reg.to64(),
98279942 Memory.sib(.byte, .{
98289943 .base = .{ .reg = addr_reg.to64() },
......@@ -9831,7 +9946,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
98319946 }),
98329947 );
98339948 try self.asmRegisterMemory(
9834 .lea,
9949 .{ ._, .lea },
98359950 end_reg.to32(),
98369951 Memory.sib(.byte, .{
98379952 .base = .{ .reg = end_reg.to64() },
......@@ -9841,7 +9956,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
98419956
98429957 const dst_mcv = try self.allocRegOrMem(inst, false);
98439958 try self.asmMemoryRegister(
9844 .mov,
9959 .{ ._, .mov },
98459960 Memory.sib(.qword, .{
98469961 .base = .{ .frame = dst_mcv.load_frame.index },
98479962 .disp = dst_mcv.load_frame.off,
......@@ -9849,7 +9964,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
98499964 start_reg.to64(),
98509965 );
98519966 try self.asmMemoryRegister(
9852 .mov,
9967 .{ ._, .mov },
98539968 Memory.sib(.qword, .{
98549969 .base = .{ .frame = dst_mcv.load_frame.index },
98559970 .disp = dst_mcv.load_frame.off + 8,
......@@ -9945,13 +10060,13 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
994510060 try self.truncateRegister(elem_ty, elem_reg);
994610061 }
994710062 if (elem_bit_off > 0) try self.genShiftBinOpMir(
9948 .shl,
10063 .{ ._l, .sh },
994910064 elem_ty,
995010065 .{ .register = elem_reg },
995110066 .{ .immediate = elem_bit_off },
995210067 );
995310068 try self.genBinOpMir(
9954 .@"or",
10069 .{ ._, .@"or" },
995510070 elem_ty,
995610071 .{ .load_frame = .{ .index = frame_index, .off = elem_byte_off } },
995710072 .{ .register = elem_reg },
......@@ -9962,13 +10077,13 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
996210077 try self.truncateRegister(elem_ty, registerAlias(reg, elem_abi_size));
996310078 }
996410079 try self.genShiftBinOpMir(
9965 .shr,
10080 .{ ._r, .sh },
996610081 elem_ty,
996710082 .{ .register = reg },
996810083 .{ .immediate = elem_abi_bits - elem_bit_off },
996910084 );
997010085 try self.genBinOpMir(
9971 .@"or",
10086 .{ ._, .@"or" },
997210087 elem_ty,
997310088 .{ .load_frame = .{
997410089 .index = frame_index,
......@@ -10078,25 +10193,25 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
1007810193 }
1007910194
1008010195 const mir_tag = if (@as(
10081 ?Mir.Inst.Tag,
10196 ?Mir.Inst.FixedTag,
1008210197 if (mem.eql(u2, &order, &.{ 1, 3, 2 }) or mem.eql(u2, &order, &.{ 3, 1, 2 }))
1008310198 switch (ty.zigTypeTag()) {
1008410199 .Float => switch (ty.floatBits(self.target.*)) {
10085 32 => .vfmadd132ss,
10086 64 => .vfmadd132sd,
10200 32 => .{ ._, .vfmadd132ss },
10201 64 => .{ ._, .vfmadd132sd },
1008710202 16, 80, 128 => null,
1008810203 else => unreachable,
1008910204 },
1009010205 .Vector => switch (ty.childType().zigTypeTag()) {
1009110206 .Float => switch (ty.childType().floatBits(self.target.*)) {
1009210207 32 => switch (ty.vectorLen()) {
10093 1 => .vfmadd132ss,
10094 2...8 => .vfmadd132ps,
10208 1 => .{ ._, .vfmadd132ss },
10209 2...8 => .{ ._, .vfmadd132ps },
1009510210 else => null,
1009610211 },
1009710212 64 => switch (ty.vectorLen()) {
10098 1 => .vfmadd132sd,
10099 2...4 => .vfmadd132pd,
10213 1 => .{ ._, .vfmadd132sd },
10214 2...4 => .{ ._, .vfmadd132pd },
1010010215 else => null,
1010110216 },
1010210217 16, 80, 128 => null,
......@@ -10109,21 +10224,21 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
1010910224 else if (mem.eql(u2, &order, &.{ 2, 1, 3 }) or mem.eql(u2, &order, &.{ 1, 2, 3 }))
1011010225 switch (ty.zigTypeTag()) {
1011110226 .Float => switch (ty.floatBits(self.target.*)) {
10112 32 => .vfmadd213ss,
10113 64 => .vfmadd213sd,
10227 32 => .{ ._, .vfmadd213ss },
10228 64 => .{ ._, .vfmadd213sd },
1011410229 16, 80, 128 => null,
1011510230 else => unreachable,
1011610231 },
1011710232 .Vector => switch (ty.childType().zigTypeTag()) {
1011810233 .Float => switch (ty.childType().floatBits(self.target.*)) {
1011910234 32 => switch (ty.vectorLen()) {
10120 1 => .vfmadd213ss,
10121 2...8 => .vfmadd213ps,
10235 1 => .{ ._, .vfmadd213ss },
10236 2...8 => .{ ._, .vfmadd213ps },
1012210237 else => null,
1012310238 },
1012410239 64 => switch (ty.vectorLen()) {
10125 1 => .vfmadd213sd,
10126 2...4 => .vfmadd213pd,
10240 1 => .{ ._, .vfmadd213sd },
10241 2...4 => .{ ._, .vfmadd213pd },
1012710242 else => null,
1012810243 },
1012910244 16, 80, 128 => null,
......@@ -10136,21 +10251,21 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
1013610251 else if (mem.eql(u2, &order, &.{ 2, 3, 1 }) or mem.eql(u2, &order, &.{ 3, 2, 1 }))
1013710252 switch (ty.zigTypeTag()) {
1013810253 .Float => switch (ty.floatBits(self.target.*)) {
10139 32 => .vfmadd231ss,
10140 64 => .vfmadd231sd,
10254 32 => .{ ._, .vfmadd231ss },
10255 64 => .{ ._, .vfmadd231sd },
1014110256 16, 80, 128 => null,
1014210257 else => unreachable,
1014310258 },
1014410259 .Vector => switch (ty.childType().zigTypeTag()) {
1014510260 .Float => switch (ty.childType().floatBits(self.target.*)) {
1014610261 32 => switch (ty.vectorLen()) {
10147 1 => .vfmadd231ss,
10148 2...8 => .vfmadd231ps,
10262 1 => .{ ._, .vfmadd231ss },
10263 2...8 => .{ ._, .vfmadd231ps },
1014910264 else => null,
1015010265 },
1015110266 64 => switch (ty.vectorLen()) {
10152 1 => .vfmadd231sd,
10153 2...4 => .vfmadd231pd,
10267 1 => .{ ._, .vfmadd231sd },
10268 2...4 => .{ ._, .vfmadd231pd },
1015410269 else => null,
1015510270 },
1015610271 16, 80, 128 => null,
......@@ -10522,17 +10637,37 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void {
1052210637 switch (int_info.signedness) {
1052310638 .signed => {
1052410639 const shift = @intCast(u6, max_reg_bit_width - int_info.bits);
10525 try self.genShiftBinOpMir(.sal, Type.isize, .{ .register = reg }, .{ .immediate = shift });
10526 try self.genShiftBinOpMir(.sar, Type.isize, .{ .register = reg }, .{ .immediate = shift });
10640 try self.genShiftBinOpMir(
10641 .{ ._l, .sa },
10642 Type.isize,
10643 .{ .register = reg },
10644 .{ .immediate = shift },
10645 );
10646 try self.genShiftBinOpMir(
10647 .{ ._r, .sa },
10648 Type.isize,
10649 .{ .register = reg },
10650 .{ .immediate = shift },
10651 );
1052710652 },
1052810653 .unsigned => {
1052910654 const shift = @intCast(u6, max_reg_bit_width - int_info.bits);
1053010655 const mask = (~@as(u64, 0)) >> shift;
1053110656 if (int_info.bits <= 32) {
10532 try self.genBinOpMir(.@"and", Type.u32, .{ .register = reg }, .{ .immediate = mask });
10657 try self.genBinOpMir(
10658 .{ ._, .@"and" },
10659 Type.u32,
10660 .{ .register = reg },
10661 .{ .immediate = mask },
10662 );
1053310663 } else {
1053410664 const tmp_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = mask });
10535 try self.genBinOpMir(.@"and", Type.usize, .{ .register = reg }, .{ .register = tmp_reg });
10665 try self.genBinOpMir(
10666 .{ ._, .@"and" },
10667 Type.usize,
10668 .{ .register = reg },
10669 .{ .register = tmp_reg },
10670 );
1053610671 }
1053710672 },
1053810673 }
src/arch/x86_64/Lower.zig+6-3
......@@ -286,10 +286,10 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
286286 .rri_s, .rri_u => inst.data.rri.fixes,
287287 .ri_s, .ri_u => inst.data.ri.fixes,
288288 .ri64, .rm_sib, .rm_rip, .mr_sib, .mr_rip => inst.data.rx.fixes,
289 .mi_sib_u, .mi_rip_u, .mi_sib_s, .mi_rip_s => ._,
290289 .mrr_sib, .mrr_rip, .rrm_sib, .rrm_rip => inst.data.rrx.fixes,
291290 .rmi_sib, .rmi_rip, .mri_sib, .mri_rip => inst.data.rix.fixes,
292291 .rrmi_sib, .rrmi_rip => inst.data.rrix.fixes,
292 .mi_sib_u, .mi_rip_u, .mi_sib_s, .mi_rip_s => inst.data.x.fixes,
293293 .m_sib, .m_rip, .rax_moffs, .moffs_rax => inst.data.x.fixes,
294294 .extern_fn_reloc, .got_reloc, .direct_reloc, .import_reloc, .tlv_reloc => ._,
295295 else => return lower.fail("TODO lower .{s}", .{@tagName(inst.ops)}),
......@@ -356,8 +356,11 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
356356 .{ .mem = lower.mem(inst.ops, inst.data.x.payload) },
357357 },
358358 .mi_sib_s, .mi_sib_u, .mi_rip_u, .mi_rip_s => &.{
359 .{ .mem = lower.mem(inst.ops, inst.data.ix.payload) },
360 .{ .imm = lower.imm(inst.ops, inst.data.ix.i) },
359 .{ .mem = lower.mem(inst.ops, inst.data.x.payload + 1) },
360 .{ .imm = lower.imm(
361 inst.ops,
362 lower.mir.extraData(Mir.Imm32, inst.data.x.payload).data.imm,
363 ) },
361364 },
362365 .rm_sib, .rm_rip => &.{
363366 .{ .reg = inst.data.rx.r1 },
src/arch/x86_64/Mir.zig+62-38
......@@ -36,6 +36,18 @@ pub const Inst = struct {
3636 /// ___
3737 @"_",
3838
39 /// Integer __
40 i_,
41
42 /// ___ Left
43 _l,
44 /// ___ Left Double
45 _ld,
46 /// ___ Right
47 _r,
48 /// ___ Right Double
49 _rd,
50
3951 /// ___ Above
4052 _a,
4153 /// ___ Above Or Equal
......@@ -53,7 +65,7 @@ pub const Inst = struct {
5365 /// ___ Greater Or Equal
5466 _ge,
5567 /// ___ Less
56 _l,
68 //_l,
5769 /// ___ Less Or Equal
5870 _le,
5971 /// ___ Not Above
......@@ -97,6 +109,15 @@ pub const Inst = struct {
97109 /// ___ Zero
98110 _z,
99111
112 /// ___ Byte
113 //_b,
114 /// ___ Word
115 _w,
116 /// ___ Doubleword
117 _d,
118 /// ___ QuadWord
119 _q,
120
100121 /// ___ String
101122 //_s,
102123 /// ___ String Byte
......@@ -165,6 +186,18 @@ pub const Inst = struct {
165186
166187 /// Locked ___
167188 @"lock _",
189 /// ___ And Complement
190 //_c,
191 /// Locked ___ And Complement
192 @"lock _c",
193 /// ___ And Reset
194 //_r,
195 /// Locked ___ And Reset
196 @"lock _r",
197 /// ___ And Set
198 //_s,
199 /// Locked ___ And Set
200 @"lock _s",
168201 /// ___ 8 Bytes
169202 _8b,
170203 /// Locked ___ 8 Bytes
......@@ -174,6 +207,11 @@ pub const Inst = struct {
174207 /// Locked ___ 16 Bytes
175208 @"lock _16b",
176209
210 /// Float ___
211 f_,
212 /// Float ___ Pop
213 f_p,
214
177215 /// Packed ___
178216 p_,
179217 /// Packed ___ Byte
......@@ -250,13 +288,10 @@ pub const Inst = struct {
250288 /// Byte swap
251289 bswap,
252290 /// Bit test
253 bt,
254291 /// Bit test and complement
255 btc,
256292 /// Bit test and reset
257 btr,
258293 /// Bit test and set
259 bts,
294 bt,
260295 /// Call
261296 call,
262297 /// Convert byte to word
......@@ -280,21 +315,18 @@ pub const Inst = struct {
280315 /// Convert word to doubleword
281316 cwde,
282317 /// Unsigned division
283 div,
284 /// Store integer with truncation
285 fisttp,
286 /// Load floating-point value
287 fld,
288318 /// Signed division
289 idiv,
290 /// Signed multiplication
291 imul,
319 div,
292320 ///
293321 int3,
322 /// Store integer with truncation
323 istt,
294324 /// Conditional jump
295325 j,
296326 /// Jump
297327 jmp,
328 /// Load floating-point value
329 ld,
298330 /// Load effective address
299331 lea,
300332 /// Load string
......@@ -307,20 +339,17 @@ pub const Inst = struct {
307339 mfence,
308340 /// Move
309341 /// Move data from string to string
342 /// Move doubleword
343 /// Move quadword
310344 mov,
311345 /// Move data after swapping bytes
312346 movbe,
313 /// Move doubleword
314 movd,
315 /// Move quadword
316 movq,
317347 /// Move with sign extension
318348 movsx,
319 /// Move with sign extension
320 movsxd,
321349 /// Move with zero extension
322350 movzx,
323351 /// Multiply
352 /// Signed multiplication
324353 mul,
325354 /// Two's complement negation
326355 neg,
......@@ -337,19 +366,16 @@ pub const Inst = struct {
337366 /// Push
338367 push,
339368 /// Rotate left through carry
340 rcl,
341369 /// Rotate right through carry
342 rcr,
370 rc,
343371 /// Return
344372 ret,
345373 /// Rotate left
346 rol,
347374 /// Rotate right
348 ror,
375 ro,
349376 /// Arithmetic shift left
350 sal,
351377 /// Arithmetic shift right
352 sar,
378 sa,
353379 /// Integer subtraction with borrow
354380 sbb,
355381 /// Scan string
......@@ -359,13 +385,10 @@ pub const Inst = struct {
359385 /// Store fence
360386 sfence,
361387 /// Logical shift left
362 shl,
363388 /// Double precision shift left
364 shld,
365389 /// Logical shift right
366 shr,
367390 /// Double precision shift right
368 shrd,
391 sh,
369392 /// Subtract
370393 sub,
371394 /// Store string
......@@ -730,6 +753,8 @@ pub const Inst = struct {
730753 pseudo,
731754 };
732755
756 pub const FixedTag = struct { Fixes, Tag };
757
733758 pub const Ops = enum(u8) {
734759 /// No data associated with this instruction (only mnemonic is used).
735760 none,
......@@ -800,16 +825,16 @@ pub const Inst = struct {
800825 /// Uses `x` with extra data of type `MemoryRip`.
801826 m_rip,
802827 /// Memory (SIB), immediate (unsigned) operands.
803 /// Uses `ix` payload with extra data of type `MemorySib`.
828 /// Uses `x` payload with extra data of type `Imm32` followed by `MemorySib`.
804829 mi_sib_u,
805830 /// Memory (RIP), immediate (unsigned) operands.
806 /// Uses `ix` payload with extra data of type `MemoryRip`.
831 /// Uses `x` payload with extra data of type `Imm32` followed by `MemoryRip`.
807832 mi_rip_u,
808833 /// Memory (SIB), immediate (sign-extend) operands.
809 /// Uses `ix` payload with extra data of type `MemorySib`.
834 /// Uses `x` payload with extra data of type `Imm32` followed by `MemorySib`.
810835 mi_sib_s,
811836 /// Memory (RIP), immediate (sign-extend) operands.
812 /// Uses `ix` payload with extra data of type `MemoryRip`.
837 /// Uses `x` payload with extra data of type `Imm32` followed by `MemoryRip`.
813838 mi_rip_s,
814839 /// Memory (SIB), register operands.
815840 /// Uses `rx` payload with extra data of type `MemorySib`.
......@@ -974,11 +999,6 @@ pub const Inst = struct {
974999 r1: Register,
9751000 payload: u32,
9761001 },
977 /// Immediate, followed by Custom payload found in extra.
978 ix: struct {
979 i: u32,
980 payload: u32,
981 },
9821002 /// Register, register, followed by Custom payload found in extra.
9831003 rrx: struct {
9841004 fixes: Fixes = ._,
......@@ -1081,6 +1101,10 @@ pub const RegisterList = struct {
10811101 }
10821102};
10831103
1104pub const Imm32 = struct {
1105 imm: u32,
1106};
1107
10841108pub const Imm64 = struct {
10851109 msb: u32,
10861110 lsb: u32,