authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-08 22:30:06-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-09 03:09:01-04:00
logf28b1657aab05f9d92fbaec243d33304f0abaec2
tree6f3b7ea853828d4356e5f105e3e63b4a378dd2a9
parent54e7f58fcb8cd3fbfd1b1a3efd090c296b0e728b

x86_64: implement 128-bit integer shifts in registers


1 files changed, 200 insertions(+), 106 deletions(-)

src/arch/x86_64/CodeGen.zig+200-106
...@@ -6427,139 +6427,233 @@ fn genShiftBinOpMir(...@@ -6427,139 +6427,233 @@ fn genShiftBinOpMir(
6427 }),6427 }),
6428 }6428 }
6429 } else if (abi_size <= 16) {6429 } else if (abi_size <= 16) {
6430 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);6430 const info: struct { indices: [2]u31, double_tag: Mir.Inst.FixedTag } = switch (tag[0]) {
6431 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);6431 ._l => .{ .indices = .{ 0, 1 }, .double_tag = .{ ._ld, .sh } },
6432 defer self.register_manager.unlockReg(tmp_lock);6432 ._r => .{ .indices = .{ 1, 0 }, .double_tag = .{ ._rd, .sh } },
6433
6434 const info: struct { offsets: [2]i32, double_tag: Mir.Inst.FixedTag } = switch (tag[0]) {
6435 ._l => .{ .offsets = .{ 0, 8 }, .double_tag = .{ ._ld, .sh } },
6436 ._r => .{ .offsets = .{ 8, 0 }, .double_tag = .{ ._rd, .sh } },
6437 else => unreachable,6433 else => unreachable,
6438 };6434 };
6439 switch (lhs_mcv) {6435 switch (lhs_mcv) {
6440 .load_frame => |dst_frame_addr| switch (rhs_mcv) {6436 .register_pair => |lhs_regs| switch (rhs_mcv) {
6441 .immediate => |rhs_imm| if (rhs_imm == 0) {} else if (rhs_imm < 64) {6437 .immediate => |rhs_imm| if (rhs_imm > 0 and rhs_imm < 64) {
6442 try self.asmRegisterMemory(6438 try self.asmRegisterRegisterImmediate(
6443 .{ ._, .mov },
6444 tmp_reg,
6445 Memory.sib(.qword, .{
6446 .base = .{ .frame = dst_frame_addr.index },
6447 .disp = dst_frame_addr.off + info.offsets[0],
6448 }),
6449 );
6450 try self.asmMemoryRegisterImmediate(
6451 info.double_tag,6439 info.double_tag,
6452 Memory.sib(.qword, .{6440 lhs_regs[info.indices[1]],
6453 .base = .{ .frame = dst_frame_addr.index },6441 lhs_regs[info.indices[0]],
6454 .disp = dst_frame_addr.off + info.offsets[1],
6455 }),
6456 tmp_reg,
6457 Immediate.u(rhs_imm),6442 Immediate.u(rhs_imm),
6458 );6443 );
6459 try self.asmMemoryImmediate(6444 try self.asmRegisterImmediate(
6460 tag,6445 tag,
6461 Memory.sib(.qword, .{6446 lhs_regs[info.indices[0]],
6462 .base = .{ .frame = dst_frame_addr.index },
6463 .disp = dst_frame_addr.off + info.offsets[0],
6464 }),
6465 Immediate.u(rhs_imm),6447 Immediate.u(rhs_imm),
6466 );6448 );
6467 } else {6449 } else {
6468 assert(rhs_imm < 128);6450 assert(rhs_imm < 128);
6469 try self.asmRegisterMemory(6451 try self.asmRegisterRegister(
6470 .{ ._, .mov },6452 .{ ._, .mov },
6471 tmp_reg,6453 lhs_regs[info.indices[1]],
6472 Memory.sib(.qword, .{6454 lhs_regs[info.indices[0]],
6473 .base = .{ .frame = dst_frame_addr.index },
6474 .disp = dst_frame_addr.off + info.offsets[0],
6475 }),
6476 );6455 );
6477 if (rhs_imm > 64) {6456 if (tag[0] == ._r and tag[1] == .sa) try self.asmRegisterImmediate(
6478 try self.asmRegisterImmediate(tag, tmp_reg, Immediate.u(rhs_imm - 64));
6479 }
6480 try self.asmMemoryRegister(
6481 .{ ._, .mov },
6482 Memory.sib(.qword, .{
6483 .base = .{ .frame = dst_frame_addr.index },
6484 .disp = dst_frame_addr.off + info.offsets[1],
6485 }),
6486 tmp_reg,
6487 );
6488 if (tag[0] == ._r and tag[1] == .sa) try self.asmMemoryImmediate(
6489 tag,6457 tag,
6490 Memory.sib(.qword, .{6458 lhs_regs[info.indices[0]],
6491 .base = .{ .frame = dst_frame_addr.index },
6492 .disp = dst_frame_addr.off + info.offsets[0],
6493 }),
6494 Immediate.u(63),6459 Immediate.u(63),
6495 ) else {6460 ) else try self.asmRegisterRegister(
6496 try self.asmRegisterRegister(.{ ._, .xor }, tmp_reg.to32(), tmp_reg.to32());6461 .{ ._, .xor },
6497 try self.asmMemoryRegister(6462 lhs_regs[info.indices[0]],
6498 .{ ._, .mov },6463 lhs_regs[info.indices[0]],
6499 Memory.sib(.qword, .{
6500 .base = .{ .frame = dst_frame_addr.index },
6501 .disp = dst_frame_addr.off + info.offsets[0],
6502 }),
6503 tmp_reg,
6504 );
6505 }
6506 },
6507 else => {
6508 const first_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
6509 const first_lock = self.register_manager.lockRegAssumeUnused(first_reg);
6510 defer self.register_manager.unlockReg(first_lock);
6511
6512 const second_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
6513 const second_lock = self.register_manager.lockRegAssumeUnused(second_reg);
6514 defer self.register_manager.unlockReg(second_lock);
6515
6516 try self.genSetReg(.cl, Type.u8, rhs_mcv);
6517 try self.asmRegisterMemory(
6518 .{ ._, .mov },
6519 first_reg,
6520 Memory.sib(.qword, .{
6521 .base = .{ .frame = dst_frame_addr.index },
6522 .disp = dst_frame_addr.off + info.offsets[0],
6523 }),
6524 );6464 );
6525 try self.asmRegisterMemory(6465 if (rhs_imm > 64) try self.asmRegisterImmediate(
6526 .{ ._, .mov },6466 tag,
6527 second_reg,6467 lhs_regs[info.indices[1]],
6528 Memory.sib(.qword, .{6468 Immediate.u(rhs_imm - 64),
6529 .base = .{ .frame = dst_frame_addr.index },
6530 .disp = dst_frame_addr.off + info.offsets[1],
6531 }),
6532 );6469 );
6470 },
6471 .register => |rhs_reg| {
6472 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
6473 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
6474 defer self.register_manager.unlockReg(tmp_lock);
6475
6533 if (tag[0] == ._r and tag[1] == .sa) {6476 if (tag[0] == ._r and tag[1] == .sa) {
6534 try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, first_reg);6477 try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, lhs_regs[info.indices[0]]);
6535 try self.asmRegisterImmediate(tag, tmp_reg, Immediate.u(63));6478 try self.asmRegisterImmediate(tag, tmp_reg, Immediate.u(63));
6536 } else try self.asmRegisterRegister(6479 } else try self.asmRegisterRegister(
6537 .{ ._, .xor },6480 .{ ._, .xor },
6538 tmp_reg.to32(),6481 tmp_reg.to32(),
6539 tmp_reg.to32(),6482 tmp_reg.to32(),
6540 );6483 );
6541 try self.asmRegisterRegisterRegister(info.double_tag, second_reg, first_reg, .cl);6484 try self.asmRegisterRegisterRegister(
6542 try self.asmRegisterRegister(tag, first_reg, .cl);6485 info.double_tag,
6543 try self.asmRegisterImmediate(.{ ._, .cmp }, .cl, Immediate.u(64));6486 lhs_regs[info.indices[1]],
6544 try self.asmCmovccRegisterRegister(second_reg, first_reg, .ae);6487 lhs_regs[info.indices[0]],
6545 try self.asmCmovccRegisterRegister(first_reg, tmp_reg, .ae);6488 registerAlias(rhs_reg, 1),
6546 try self.asmMemoryRegister(
6547 .{ ._, .mov },
6548 Memory.sib(.qword, .{
6549 .base = .{ .frame = dst_frame_addr.index },
6550 .disp = dst_frame_addr.off + info.offsets[1],
6551 }),
6552 second_reg,
6553 );6489 );
6554 try self.asmMemoryRegister(6490 try self.asmRegisterRegister(
6555 .{ ._, .mov },6491 tag,
6556 Memory.sib(.qword, .{6492 lhs_regs[info.indices[0]],
6557 .base = .{ .frame = dst_frame_addr.index },6493 registerAlias(rhs_reg, 1),
6558 .disp = dst_frame_addr.off + info.offsets[0],6494 );
6559 }),6495 try self.asmRegisterImmediate(
6560 first_reg,6496 .{ ._, .cmp },
6497 registerAlias(rhs_reg, 1),
6498 Immediate.u(64),
6561 );6499 );
6500 try self.asmCmovccRegisterRegister(
6501 lhs_regs[info.indices[1]],
6502 lhs_regs[info.indices[0]],
6503 .ae,
6504 );
6505 try self.asmCmovccRegisterRegister(lhs_regs[info.indices[0]], tmp_reg, .ae);
6562 },6506 },
6507 else => return self.fail("TODO genShiftBinOpMir between {s} and {s}", .{
6508 @tagName(lhs_mcv),
6509 @tagName(rhs_mcv),
6510 }),
6511 },
6512 .load_frame => |dst_frame_addr| {
6513 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
6514 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
6515 defer self.register_manager.unlockReg(tmp_lock);
6516
6517 switch (rhs_mcv) {
6518 .immediate => |rhs_imm| if (rhs_imm > 0 and rhs_imm < 64) {
6519 try self.asmRegisterMemory(
6520 .{ ._, .mov },
6521 tmp_reg,
6522 Memory.sib(.qword, .{
6523 .base = .{ .frame = dst_frame_addr.index },
6524 .disp = dst_frame_addr.off + info.indices[0] * 8,
6525 }),
6526 );
6527 try self.asmMemoryRegisterImmediate(
6528 info.double_tag,
6529 Memory.sib(.qword, .{
6530 .base = .{ .frame = dst_frame_addr.index },
6531 .disp = dst_frame_addr.off + info.indices[1] * 8,
6532 }),
6533 tmp_reg,
6534 Immediate.u(rhs_imm),
6535 );
6536 try self.asmMemoryImmediate(
6537 tag,
6538 Memory.sib(.qword, .{
6539 .base = .{ .frame = dst_frame_addr.index },
6540 .disp = dst_frame_addr.off + info.indices[0] * 8,
6541 }),
6542 Immediate.u(rhs_imm),
6543 );
6544 } else {
6545 assert(rhs_imm < 128);
6546 try self.asmRegisterMemory(
6547 .{ ._, .mov },
6548 tmp_reg,
6549 Memory.sib(.qword, .{
6550 .base = .{ .frame = dst_frame_addr.index },
6551 .disp = dst_frame_addr.off + info.indices[0] * 8,
6552 }),
6553 );
6554 if (rhs_imm > 64) try self.asmRegisterImmediate(
6555 tag,
6556 tmp_reg,
6557 Immediate.u(rhs_imm - 64),
6558 );
6559 try self.asmMemoryRegister(
6560 .{ ._, .mov },
6561 Memory.sib(.qword, .{
6562 .base = .{ .frame = dst_frame_addr.index },
6563 .disp = dst_frame_addr.off + info.indices[1] * 8,
6564 }),
6565 tmp_reg,
6566 );
6567 if (tag[0] == ._r and tag[1] == .sa) try self.asmMemoryImmediate(
6568 tag,
6569 Memory.sib(.qword, .{
6570 .base = .{ .frame = dst_frame_addr.index },
6571 .disp = dst_frame_addr.off + info.indices[0] * 8,
6572 }),
6573 Immediate.u(63),
6574 ) else {
6575 try self.asmRegisterRegister(.{ ._, .xor }, tmp_reg.to32(), tmp_reg.to32());
6576 try self.asmMemoryRegister(
6577 .{ ._, .mov },
6578 Memory.sib(.qword, .{
6579 .base = .{ .frame = dst_frame_addr.index },
6580 .disp = dst_frame_addr.off + info.indices[0] * 8,
6581 }),
6582 tmp_reg,
6583 );
6584 }
6585 },
6586 .register => |rhs_reg| {
6587 const first_reg =
6588 try self.register_manager.allocReg(null, abi.RegisterClass.gp);
6589 const first_lock = self.register_manager.lockRegAssumeUnused(first_reg);
6590 defer self.register_manager.unlockReg(first_lock);
6591
6592 const second_reg =
6593 try self.register_manager.allocReg(null, abi.RegisterClass.gp);
6594 const second_lock = self.register_manager.lockRegAssumeUnused(second_reg);
6595 defer self.register_manager.unlockReg(second_lock);
6596
6597 try self.asmRegisterMemory(
6598 .{ ._, .mov },
6599 first_reg,
6600 Memory.sib(.qword, .{
6601 .base = .{ .frame = dst_frame_addr.index },
6602 .disp = dst_frame_addr.off + info.indices[0] * 8,
6603 }),
6604 );
6605 try self.asmRegisterMemory(
6606 .{ ._, .mov },
6607 second_reg,
6608 Memory.sib(.qword, .{
6609 .base = .{ .frame = dst_frame_addr.index },
6610 .disp = dst_frame_addr.off + info.indices[1] * 8,
6611 }),
6612 );
6613 if (tag[0] == ._r and tag[1] == .sa) {
6614 try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, first_reg);
6615 try self.asmRegisterImmediate(tag, tmp_reg, Immediate.u(63));
6616 } else try self.asmRegisterRegister(
6617 .{ ._, .xor },
6618 tmp_reg.to32(),
6619 tmp_reg.to32(),
6620 );
6621 try self.asmRegisterRegisterRegister(
6622 info.double_tag,
6623 second_reg,
6624 first_reg,
6625 registerAlias(rhs_reg, 1),
6626 );
6627 try self.asmRegisterRegister(tag, first_reg, registerAlias(rhs_reg, 1));
6628 try self.asmRegisterImmediate(
6629 .{ ._, .cmp },
6630 registerAlias(rhs_reg, 1),
6631 Immediate.u(64),
6632 );
6633 try self.asmCmovccRegisterRegister(second_reg, first_reg, .ae);
6634 try self.asmCmovccRegisterRegister(first_reg, tmp_reg, .ae);
6635 try self.asmMemoryRegister(
6636 .{ ._, .mov },
6637 Memory.sib(.qword, .{
6638 .base = .{ .frame = dst_frame_addr.index },
6639 .disp = dst_frame_addr.off + info.indices[1] * 8,
6640 }),
6641 second_reg,
6642 );
6643 try self.asmMemoryRegister(
6644 .{ ._, .mov },
6645 Memory.sib(.qword, .{
6646 .base = .{ .frame = dst_frame_addr.index },
6647 .disp = dst_frame_addr.off + info.indices[0] * 8,
6648 }),
6649 first_reg,
6650 );
6651 },
6652 else => return self.fail("TODO genShiftBinOpMir between {s} and {s}", .{
6653 @tagName(lhs_mcv),
6654 @tagName(rhs_mcv),
6655 }),
6656 }
6563 },6657 },
6564 else => return self.fail("TODO genShiftBinOpMir between {s} and {s}", .{6658 else => return self.fail("TODO genShiftBinOpMir between {s} and {s}", .{
6565 @tagName(lhs_mcv),6659 @tagName(lhs_mcv),