| ... | @@ -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), |