| ... | ... | @@ -6427,139 +6427,233 @@ fn genShiftBinOpMir( |
| 6427 | 6427 | }), |
| 6428 | 6428 | } |
| 6429 | 6429 | } else if (abi_size <= 16) { |
| 6430 | | const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 6431 | | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 6432 | | defer self.register_manager.unlockReg(tmp_lock); |
| 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 } }, |
| 6430 | const info: struct { indices: [2]u31, double_tag: Mir.Inst.FixedTag } = switch (tag[0]) { |
| 6431 | ._l => .{ .indices = .{ 0, 1 }, .double_tag = .{ ._ld, .sh } }, |
| 6432 | ._r => .{ .indices = .{ 1, 0 }, .double_tag = .{ ._rd, .sh } }, |
| 6437 | 6433 | else => unreachable, |
| 6438 | 6434 | }; |
| 6439 | 6435 | switch (lhs_mcv) { |
| 6440 | | .load_frame => |dst_frame_addr| switch (rhs_mcv) { |
| 6441 | | .immediate => |rhs_imm| if (rhs_imm == 0) {} else if (rhs_imm < 64) { |
| 6442 | | try self.asmRegisterMemory( |
| 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( |
| 6436 | .register_pair => |lhs_regs| switch (rhs_mcv) { |
| 6437 | .immediate => |rhs_imm| if (rhs_imm > 0 and rhs_imm < 64) { |
| 6438 | try self.asmRegisterRegisterImmediate( |
| 6451 | 6439 | info.double_tag, |
| 6452 | | Memory.sib(.qword, .{ |
| 6453 | | .base = .{ .frame = dst_frame_addr.index }, |
| 6454 | | .disp = dst_frame_addr.off + info.offsets[1], |
| 6455 | | }), |
| 6456 | | tmp_reg, |
| 6440 | lhs_regs[info.indices[1]], |
| 6441 | lhs_regs[info.indices[0]], |
| 6457 | 6442 | Immediate.u(rhs_imm), |
| 6458 | 6443 | ); |
| 6459 | | try self.asmMemoryImmediate( |
| 6444 | try self.asmRegisterImmediate( |
| 6460 | 6445 | tag, |
| 6461 | | Memory.sib(.qword, .{ |
| 6462 | | .base = .{ .frame = dst_frame_addr.index }, |
| 6463 | | .disp = dst_frame_addr.off + info.offsets[0], |
| 6464 | | }), |
| 6446 | lhs_regs[info.indices[0]], |
| 6465 | 6447 | Immediate.u(rhs_imm), |
| 6466 | 6448 | ); |
| 6467 | 6449 | } else { |
| 6468 | 6450 | assert(rhs_imm < 128); |
| 6469 | | try self.asmRegisterMemory( |
| 6451 | try self.asmRegisterRegister( |
| 6470 | 6452 | .{ ._, .mov }, |
| 6471 | | tmp_reg, |
| 6472 | | Memory.sib(.qword, .{ |
| 6473 | | .base = .{ .frame = dst_frame_addr.index }, |
| 6474 | | .disp = dst_frame_addr.off + info.offsets[0], |
| 6475 | | }), |
| 6453 | lhs_regs[info.indices[1]], |
| 6454 | lhs_regs[info.indices[0]], |
| 6476 | 6455 | ); |
| 6477 | | if (rhs_imm > 64) { |
| 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( |
| 6456 | if (tag[0] == ._r and tag[1] == .sa) try self.asmRegisterImmediate( |
| 6489 | 6457 | tag, |
| 6490 | | Memory.sib(.qword, .{ |
| 6491 | | .base = .{ .frame = dst_frame_addr.index }, |
| 6492 | | .disp = dst_frame_addr.off + info.offsets[0], |
| 6493 | | }), |
| 6458 | lhs_regs[info.indices[0]], |
| 6494 | 6459 | Immediate.u(63), |
| 6495 | | ) else { |
| 6496 | | try self.asmRegisterRegister(.{ ._, .xor }, tmp_reg.to32(), tmp_reg.to32()); |
| 6497 | | try self.asmMemoryRegister( |
| 6498 | | .{ ._, .mov }, |
| 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 | | }), |
| 6460 | ) else try self.asmRegisterRegister( |
| 6461 | .{ ._, .xor }, |
| 6462 | lhs_regs[info.indices[0]], |
| 6463 | lhs_regs[info.indices[0]], |
| 6524 | 6464 | ); |
| 6525 | | try self.asmRegisterMemory( |
| 6526 | | .{ ._, .mov }, |
| 6527 | | second_reg, |
| 6528 | | Memory.sib(.qword, .{ |
| 6529 | | .base = .{ .frame = dst_frame_addr.index }, |
| 6530 | | .disp = dst_frame_addr.off + info.offsets[1], |
| 6531 | | }), |
| 6465 | if (rhs_imm > 64) try self.asmRegisterImmediate( |
| 6466 | tag, |
| 6467 | lhs_regs[info.indices[1]], |
| 6468 | Immediate.u(rhs_imm - 64), |
| 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 | 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 | 6478 | try self.asmRegisterImmediate(tag, tmp_reg, Immediate.u(63)); |
| 6536 | 6479 | } else try self.asmRegisterRegister( |
| 6537 | 6480 | .{ ._, .xor }, |
| 6538 | 6481 | tmp_reg.to32(), |
| 6539 | 6482 | tmp_reg.to32(), |
| 6540 | 6483 | ); |
| 6541 | | try self.asmRegisterRegisterRegister(info.double_tag, second_reg, first_reg, .cl); |
| 6542 | | try self.asmRegisterRegister(tag, first_reg, .cl); |
| 6543 | | try self.asmRegisterImmediate(.{ ._, .cmp }, .cl, Immediate.u(64)); |
| 6544 | | try self.asmCmovccRegisterRegister(second_reg, first_reg, .ae); |
| 6545 | | try self.asmCmovccRegisterRegister(first_reg, tmp_reg, .ae); |
| 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, |
| 6484 | try self.asmRegisterRegisterRegister( |
| 6485 | info.double_tag, |
| 6486 | lhs_regs[info.indices[1]], |
| 6487 | lhs_regs[info.indices[0]], |
| 6488 | registerAlias(rhs_reg, 1), |
| 6553 | 6489 | ); |
| 6554 | | try self.asmMemoryRegister( |
| 6555 | | .{ ._, .mov }, |
| 6556 | | Memory.sib(.qword, .{ |
| 6557 | | .base = .{ .frame = dst_frame_addr.index }, |
| 6558 | | .disp = dst_frame_addr.off + info.offsets[0], |
| 6559 | | }), |
| 6560 | | first_reg, |
| 6490 | try self.asmRegisterRegister( |
| 6491 | tag, |
| 6492 | lhs_regs[info.indices[0]], |
| 6493 | registerAlias(rhs_reg, 1), |
| 6494 | ); |
| 6495 | try self.asmRegisterImmediate( |
| 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 | 6658 | else => return self.fail("TODO genShiftBinOpMir between {s} and {s}", .{ |
| 6565 | 6659 | @tagName(lhs_mcv), |