| ... | ... | @@ -491,6 +491,72 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Imme |
| 491 | 491 | }); |
| 492 | 492 | } |
| 493 | 493 | |
| 494 | fn asmMemory(self: *Self, tag: Mir.Inst.Tag, m: Memory) !void { |
| 495 | const ops: Mir.Inst.Ops = switch (m) { |
| 496 | .sib => .m_sib, |
| 497 | .rip => .m_rip, |
| 498 | else => unreachable, |
| 499 | }; |
| 500 | const data: Mir.Inst.Data = switch (ops) { |
| 501 | .m_sib => .{ .payload = try self.addExtra(Mir.MemorySib.encode(m)) }, |
| 502 | .m_rip => .{ .payload = try self.addExtra(Mir.MemoryRip.encode(m)) }, |
| 503 | else => unreachable, |
| 504 | }; |
| 505 | _ = try self.addInst(.{ |
| 506 | .tag = tag, |
| 507 | .ops = ops, |
| 508 | .data = data, |
| 509 | }); |
| 510 | } |
| 511 | |
| 512 | fn asmRegisterMemory(self: *Self, tag: Mir.Inst.Tag, reg: Register, m: Memory) !void { |
| 513 | const ops: Mir.Inst.Ops = switch (m) { |
| 514 | .sib => .rm_sib, |
| 515 | .rip => .rm_rip, |
| 516 | else => unreachable, |
| 517 | }; |
| 518 | const data: Mir.Inst.Data = switch (ops) { |
| 519 | .rm_sib => .{ .rx = .{ |
| 520 | .r1 = reg, |
| 521 | .payload = try self.addExtra(Mir.MemorySib.encode(m)), |
| 522 | } }, |
| 523 | .rm_rip => .{ .rx = .{ |
| 524 | .r1 = reg, |
| 525 | .payload = try self.addExtra(Mir.MemoryRip.encode(m)), |
| 526 | } }, |
| 527 | else => unreachable, |
| 528 | }; |
| 529 | _ = try self.addInst(.{ |
| 530 | .tag = tag, |
| 531 | .ops = ops, |
| 532 | .data = data, |
| 533 | }); |
| 534 | } |
| 535 | |
| 536 | fn asmMemoryRegister(self: *Self, tag: Mir.Inst.Tag, m: Memory, reg: Register) !void { |
| 537 | const ops: Mir.Inst.Ops = switch (m) { |
| 538 | .sib => .mr_sib, |
| 539 | .rip => .mr_rip, |
| 540 | else => unreachable, |
| 541 | }; |
| 542 | const data: Mir.Inst.Data = switch (ops) { |
| 543 | .mr_sib => .{ .rx = .{ |
| 544 | .r1 = reg, |
| 545 | .payload = try self.addExtra(Mir.MemorySib.encode(m)), |
| 546 | } }, |
| 547 | .mr_rip => .{ .rx = .{ |
| 548 | .r1 = reg, |
| 549 | .payload = try self.addExtra(Mir.MemoryRip.encode(m)), |
| 550 | } }, |
| 551 | else => unreachable, |
| 552 | }; |
| 553 | _ = try self.addInst(.{ |
| 554 | .tag = tag, |
| 555 | .ops = ops, |
| 556 | .data = data, |
| 557 | }); |
| 558 | } |
| 559 | |
| 494 | 560 | fn gen(self: *Self) InnerError!void { |
| 495 | 561 | const cc = self.fn_type.fnCallingConvention(); |
| 496 | 562 | if (cc != .Naked) { |
| ... | ... | @@ -1741,23 +1807,10 @@ fn genIntMulDivOpMir( |
| 1741 | 1807 | |
| 1742 | 1808 | switch (factor) { |
| 1743 | 1809 | .register => |reg| try self.asmRegister(tag, reg), |
| 1744 | | .stack_offset => |off| { |
| 1745 | | _ = off; |
| 1746 | | // _ = try self.addInst(.{ |
| 1747 | | // .tag = tag, |
| 1748 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 1749 | | // .reg2 = .rbp, |
| 1750 | | // .flags = switch (abi_size) { |
| 1751 | | // 1 => 0b00, |
| 1752 | | // 2 => 0b01, |
| 1753 | | // 4 => 0b10, |
| 1754 | | // 8 => 0b11, |
| 1755 | | // else => unreachable, |
| 1756 | | // }, |
| 1757 | | // }), |
| 1758 | | // .data = .{ .disp = -off }, |
| 1759 | | // }); |
| 1760 | | }, |
| 1810 | .stack_offset => |off| try self.asmMemory(tag, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 1811 | .base = .rbp, |
| 1812 | .disp = -off, |
| 1813 | })), |
| 1761 | 1814 | else => unreachable, |
| 1762 | 1815 | } |
| 1763 | 1816 | } |
| ... | ... | @@ -2222,19 +2275,10 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { |
| 2222 | 2275 | |
| 2223 | 2276 | const addr_reg = try self.register_manager.allocReg(null, gp); |
| 2224 | 2277 | switch (slice_mcv) { |
| 2225 | | .stack_offset => |off| { |
| 2226 | | _ = off; |
| 2227 | | // mov reg, [rbp - 8] |
| 2228 | | // _ = try self.addInst(.{ |
| 2229 | | // .tag = .mov, |
| 2230 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 2231 | | // .reg1 = addr_reg.to64(), |
| 2232 | | // .reg2 = .rbp, |
| 2233 | | // .flags = 0b01, |
| 2234 | | // }), |
| 2235 | | // .data = .{ .disp = -@intCast(i32, off) }, |
| 2236 | | // }); |
| 2237 | | }, |
| 2278 | .stack_offset => |off| try self.asmRegisterMemory(.mov, addr_reg.to64(), Memory.sib(.qword, .{ |
| 2279 | .base = .rbp, |
| 2280 | .disp = -off, |
| 2281 | })), |
| 2238 | 2282 | else => return self.fail("TODO implement slice_elem_ptr when slice is {}", .{slice_mcv}), |
| 2239 | 2283 | } |
| 2240 | 2284 | // TODO we could allocate register here, but need to expect addr register and potentially |
| ... | ... | @@ -2309,27 +2353,16 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2309 | 2353 | array_ty.abiAlignment(self.target.*), |
| 2310 | 2354 | )); |
| 2311 | 2355 | try self.genSetStack(array_ty, off, array, .{}); |
| 2312 | | // lea reg, [rbp] |
| 2313 | | // _ = try self.addInst(.{ |
| 2314 | | // .tag = .lea, |
| 2315 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 2316 | | // .reg1 = addr_reg.to64(), |
| 2317 | | // .reg2 = .rbp, |
| 2318 | | // }), |
| 2319 | | // .data = .{ .disp = -off }, |
| 2320 | | // }); |
| 2356 | try self.asmRegisterMemory(.lea, addr_reg.to64(), Memory.sib(.qword, .{ |
| 2357 | .base = .rbp, |
| 2358 | .disp = -off, |
| 2359 | })); |
| 2321 | 2360 | }, |
| 2322 | 2361 | .stack_offset => |off| { |
| 2323 | | _ = off; |
| 2324 | | // lea reg, [rbp] |
| 2325 | | // _ = try self.addInst(.{ |
| 2326 | | // .tag = .lea, |
| 2327 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 2328 | | // .reg1 = addr_reg.to64(), |
| 2329 | | // .reg2 = .rbp, |
| 2330 | | // }), |
| 2331 | | // .data = .{ .disp = -off }, |
| 2332 | | // }); |
| 2362 | try self.asmRegisterMemory(.lea, addr_reg.to64(), Memory.sib(.qword, .{ |
| 2363 | .base = .rbp, |
| 2364 | .disp = -off, |
| 2365 | })); |
| 2333 | 2366 | }, |
| 2334 | 2367 | .memory, .linker_load => { |
| 2335 | 2368 | try self.loadMemPtrIntoRegister(addr_reg, Type.usize, array); |
| ... | ... | @@ -2366,7 +2399,7 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2366 | 2399 | defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock); |
| 2367 | 2400 | |
| 2368 | 2401 | const elem_ty = ptr_ty.elemType2(); |
| 2369 | | const elem_abi_size = elem_ty.abiSize(self.target.*); |
| 2402 | const elem_abi_size = @intCast(u32, elem_ty.abiSize(self.target.*)); |
| 2370 | 2403 | const index_ty = self.air.typeOf(bin_op.rhs); |
| 2371 | 2404 | const index = try self.resolveInst(bin_op.rhs); |
| 2372 | 2405 | const index_lock: ?RegisterLock = switch (index) { |
| ... | ... | @@ -2386,16 +2419,14 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2386 | 2419 | if (elem_abi_size > 8) { |
| 2387 | 2420 | return self.fail("TODO copy value with size {} from pointer", .{elem_abi_size}); |
| 2388 | 2421 | } else { |
| 2389 | | // mov dst_mcv, [dst_mcv] |
| 2390 | | // _ = try self.addInst(.{ |
| 2391 | | // .tag = .mov, |
| 2392 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 2393 | | // .reg1 = registerAlias(dst_mcv.register, @intCast(u32, elem_abi_size)), |
| 2394 | | // .reg2 = dst_mcv.register, |
| 2395 | | // .flags = 0b01, |
| 2396 | | // }), |
| 2397 | | // .data = .{ .disp = 0 }, |
| 2398 | | // }); |
| 2422 | try self.asmRegisterMemory( |
| 2423 | .mov, |
| 2424 | registerAlias(dst_mcv.register, elem_abi_size), |
| 2425 | Memory.sib(Memory.PtrSize.fromSize(elem_abi_size), .{ |
| 2426 | .base = dst_mcv.register, |
| 2427 | .disp = 0, |
| 2428 | }), |
| 2429 | ); |
| 2399 | 2430 | break :result .{ .register = registerAlias(dst_mcv.register, @intCast(u32, elem_abi_size)) }; |
| 2400 | 2431 | } |
| 2401 | 2432 | }; |
| ... | ... | @@ -2622,7 +2653,7 @@ fn reuseOperand( |
| 2622 | 2653 | |
| 2623 | 2654 | fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void { |
| 2624 | 2655 | const elem_ty = ptr_ty.elemType(); |
| 2625 | | const abi_size = elem_ty.abiSize(self.target.*); |
| 2656 | const abi_size = @intCast(u32, elem_ty.abiSize(self.target.*)); |
| 2626 | 2657 | switch (ptr) { |
| 2627 | 2658 | .none => unreachable, |
| 2628 | 2659 | .undef => unreachable, |
| ... | ... | @@ -2649,17 +2680,11 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 2649 | 2680 | .undef => unreachable, |
| 2650 | 2681 | .eflags => unreachable, |
| 2651 | 2682 | .register => |dst_reg| { |
| 2652 | | _ = dst_reg; |
| 2653 | | // mov dst_reg, [reg] |
| 2654 | | // _ = try self.addInst(.{ |
| 2655 | | // .tag = .mov, |
| 2656 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 2657 | | // .reg1 = registerAlias(dst_reg, @intCast(u32, abi_size)), |
| 2658 | | // .reg2 = reg, |
| 2659 | | // .flags = 0b01, |
| 2660 | | // }), |
| 2661 | | // .data = .{ .disp = 0 }, |
| 2662 | | // }); |
| 2683 | try self.asmRegisterMemory( |
| 2684 | .mov, |
| 2685 | registerAlias(dst_reg, abi_size), |
| 2686 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = reg, .disp = 0 }), |
| 2687 | ); |
| 2663 | 2688 | }, |
| 2664 | 2689 | .stack_offset => |off| { |
| 2665 | 2690 | if (abi_size <= 8) { |
| ... | ... | @@ -2874,17 +2899,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2874 | 2899 | |
| 2875 | 2900 | try self.loadMemPtrIntoRegister(addr_reg, ptr_ty, ptr); |
| 2876 | 2901 | |
| 2877 | | // to get the actual address of the value we want to modify we have to go through the GOT |
| 2878 | | // mov reg, [reg] |
| 2879 | | // _ = try self.addInst(.{ |
| 2880 | | // .tag = .mov, |
| 2881 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 2882 | | // .reg1 = addr_reg.to64(), |
| 2883 | | // .reg2 = addr_reg.to64(), |
| 2884 | | // .flags = 0b01, |
| 2885 | | // }), |
| 2886 | | // .data = .{ .disp = 0 }, |
| 2887 | | // }); |
| 2902 | // To get the actual address of the value we want to modify we have to go through the GOT |
| 2903 | try self.asmRegisterMemory(.mov, addr_reg.to64(), Memory.sib(.qword, .{ |
| 2904 | .base = addr_reg.to64(), |
| 2905 | .disp = 0, |
| 2906 | })); |
| 2888 | 2907 | |
| 2889 | 2908 | const new_ptr = MCValue{ .register = addr_reg.to64() }; |
| 2890 | 2909 | |
| ... | ... | @@ -2936,16 +2955,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2936 | 2955 | defer self.register_manager.unlockReg(tmp_reg_lock); |
| 2937 | 2956 | |
| 2938 | 2957 | try self.loadMemPtrIntoRegister(tmp_reg, value_ty, value); |
| 2958 | try self.asmRegisterMemory(.mov, tmp_reg, Memory.sib(.qword, .{ |
| 2959 | .base = tmp_reg, |
| 2960 | .disp = 0, |
| 2961 | })); |
| 2939 | 2962 | |
| 2940 | | // _ = try self.addInst(.{ |
| 2941 | | // .tag = .mov, |
| 2942 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 2943 | | // .reg1 = tmp_reg, |
| 2944 | | // .reg2 = tmp_reg, |
| 2945 | | // .flags = 0b01, |
| 2946 | | // }), |
| 2947 | | // .data = .{ .disp = 0 }, |
| 2948 | | // }); |
| 2949 | 2963 | return self.store(new_ptr, .{ .register = tmp_reg }, ptr_ty, value_ty); |
| 2950 | 2964 | } |
| 2951 | 2965 | |
| ... | ... | @@ -3603,15 +3617,11 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3603 | 3617 | if (off > math.maxInt(i32)) { |
| 3604 | 3618 | return self.fail("stack offset too large", .{}); |
| 3605 | 3619 | } |
| 3606 | | // _ = try self.addInst(.{ |
| 3607 | | // .tag = mir_tag, |
| 3608 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 3609 | | // .reg1 = registerAlias(dst_reg, abi_size), |
| 3610 | | // .reg2 = .rbp, |
| 3611 | | // .flags = 0b01, |
| 3612 | | // }), |
| 3613 | | // .data = .{ .disp = -off }, |
| 3614 | | // }); |
| 3620 | try self.asmRegisterMemory( |
| 3621 | mir_tag, |
| 3622 | registerAlias(dst_reg, abi_size), |
| 3623 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .rbp, .disp = -off }), |
| 3624 | ); |
| 3615 | 3625 | }, |
| 3616 | 3626 | } |
| 3617 | 3627 | }, |
| ... | ... | @@ -3629,16 +3639,10 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3629 | 3639 | .dead, .unreach => unreachable, |
| 3630 | 3640 | .register_overflow => unreachable, |
| 3631 | 3641 | .register => |src_reg| { |
| 3632 | | _ = src_reg; |
| 3633 | | // _ = try self.addInst(.{ |
| 3634 | | // .tag = mir_tag, |
| 3635 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 3636 | | // .reg1 = .rbp, |
| 3637 | | // .reg2 = registerAlias(src_reg, abi_size), |
| 3638 | | // .flags = 0b10, |
| 3639 | | // }), |
| 3640 | | // .data = .{ .disp = -off }, |
| 3641 | | // }); |
| 3642 | try self.asmMemoryRegister(mir_tag, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 3643 | .base = .rbp, |
| 3644 | .disp = -off, |
| 3645 | }), registerAlias(src_reg, abi_size)); |
| 3642 | 3646 | }, |
| 3643 | 3647 | .immediate => |imm| { |
| 3644 | 3648 | _ = imm; |
| ... | ... | @@ -3738,16 +3742,11 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 3738 | 3742 | } |
| 3739 | 3743 | }, |
| 3740 | 3744 | .stack_offset => |off| { |
| 3741 | | _ = off; |
| 3742 | | // _ = try self.addInst(.{ |
| 3743 | | // .tag = .imul_complex, |
| 3744 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 3745 | | // .reg1 = registerAlias(dst_reg, abi_size), |
| 3746 | | // .reg2 = .rbp, |
| 3747 | | // .flags = 0b01, |
| 3748 | | // }), |
| 3749 | | // .data = .{ .disp = -off }, |
| 3750 | | // }); |
| 3745 | try self.asmRegisterMemory( |
| 3746 | .imul, |
| 3747 | registerAlias(dst_reg, abi_size), |
| 3748 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .rbp, .disp = -off }), |
| 3749 | ); |
| 3751 | 3750 | }, |
| 3752 | 3751 | .memory => { |
| 3753 | 3752 | return self.fail("TODO implement x86 multiply source memory", .{}); |
| ... | ... | @@ -3770,17 +3769,11 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 3770 | 3769 | .register => |src_reg| { |
| 3771 | 3770 | // copy dst to a register |
| 3772 | 3771 | const dst_reg = try self.copyToTmpRegister(dst_ty, dst_mcv); |
| 3773 | | _ = src_reg; |
| 3774 | | // multiply into dst_reg |
| 3775 | | // register, register |
| 3776 | | // _ = try self.addInst(.{ |
| 3777 | | // .tag = .imul_complex, |
| 3778 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 3779 | | // .reg1 = registerAlias(dst_reg, abi_size), |
| 3780 | | // .reg2 = registerAlias(src_reg, abi_size), |
| 3781 | | // }), |
| 3782 | | // .data = undefined, |
| 3783 | | // }); |
| 3772 | try self.asmRegisterRegister( |
| 3773 | .imul, |
| 3774 | registerAlias(dst_reg, abi_size), |
| 3775 | registerAlias(src_reg, abi_size), |
| 3776 | ); |
| 3784 | 3777 | // copy dst_reg back out |
| 3785 | 3778 | return self.genSetStack(dst_ty, off, .{ .register = dst_reg }, .{}); |
| 3786 | 3779 | }, |
| ... | ... | @@ -4006,11 +3999,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 4006 | 3999 | |
| 4007 | 4000 | if (info.stack_byte_count > 0) { |
| 4008 | 4001 | // Adjust the stack |
| 4009 | | // _ = try self.addInst(.{ |
| 4010 | | // .tag = .sub, |
| 4011 | | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = .rsp }), |
| 4012 | | // .data = .{ .imm = info.stack_byte_count }, |
| 4013 | | // }); |
| 4002 | try self.asmRegisterImmediate(.sub, .rsp, Immediate.u(info.stack_byte_count)); |
| 4014 | 4003 | } |
| 4015 | 4004 | |
| 4016 | 4005 | // Due to incremental compilation, how function calls are generated depends |
| ... | ... | @@ -4161,7 +4150,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 4161 | 4150 | // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction |
| 4162 | 4151 | // which is available if the jump is 127 bytes or less forward. |
| 4163 | 4152 | const jmp_reloc = try self.addInst(.{ |
| 4164 | | .tag = .jmp, |
| 4153 | .tag = .jmp_reloc, |
| 4165 | 4154 | .ops = .inst, |
| 4166 | 4155 | .data = .{ .inst = undefined }, |
| 4167 | 4156 | }); |
| ... | ... | @@ -4197,7 +4186,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 4197 | 4186 | // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction |
| 4198 | 4187 | // which is available if the jump is 127 bytes or less forward. |
| 4199 | 4188 | const jmp_reloc = try self.addInst(.{ |
| 4200 | | .tag = .jmp, |
| 4189 | .tag = .jmp_reloc, |
| 4201 | 4190 | .ops = .inst, |
| 4202 | 4191 | .data = .{ .inst = undefined }, |
| 4203 | 4192 | }); |
| ... | ... | @@ -4738,7 +4727,7 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void { |
| 4738 | 4727 | const jmp_target = @intCast(u32, self.mir_instructions.len); |
| 4739 | 4728 | try self.genBody(body); |
| 4740 | 4729 | _ = try self.addInst(.{ |
| 4741 | | .tag = .jmp, |
| 4730 | .tag = .jmp_reloc, |
| 4742 | 4731 | .ops = .inst, |
| 4743 | 4732 | .data = .{ .inst = jmp_target }, |
| 4744 | 4733 | }); |
| ... | ... | @@ -5035,7 +5024,7 @@ fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void { |
| 5035 | 5024 | .jcc => { |
| 5036 | 5025 | self.mir_instructions.items(.data)[reloc].inst_cc.inst = next_inst; |
| 5037 | 5026 | }, |
| 5038 | | .jmp => { |
| 5027 | .jmp_reloc => { |
| 5039 | 5028 | self.mir_instructions.items(.data)[reloc].inst = next_inst; |
| 5040 | 5029 | }, |
| 5041 | 5030 | else => unreachable, |
| ... | ... | @@ -5078,7 +5067,7 @@ fn brVoid(self: *Self, block: Air.Inst.Index) !void { |
| 5078 | 5067 | try block_data.relocs.ensureUnusedCapacity(self.gpa, 1); |
| 5079 | 5068 | // Leave the jump offset undefined |
| 5080 | 5069 | const jmp_reloc = try self.addInst(.{ |
| 5081 | | .tag = .jmp, |
| 5070 | .tag = .jmp_reloc, |
| 5082 | 5071 | .ops = .inst, |
| 5083 | 5072 | .data = .{ .inst = undefined }, |
| 5084 | 5073 | }); |
| ... | ... | @@ -5247,7 +5236,7 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void { |
| 5247 | 5236 | } |
| 5248 | 5237 | |
| 5249 | 5238 | fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerError!void { |
| 5250 | | const abi_size = ty.abiSize(self.target.*); |
| 5239 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 5251 | 5240 | switch (mcv) { |
| 5252 | 5241 | .dead => unreachable, |
| 5253 | 5242 | .unreach, .none => return, |
| ... | ... | @@ -5325,36 +5314,25 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 5325 | 5314 | .{ty.fmtDebug()}, |
| 5326 | 5315 | ), |
| 5327 | 5316 | }; |
| 5328 | | _ = tag; |
| 5329 | | _ = reg; |
| 5330 | | // _ = try self.addInst(.{ |
| 5331 | | // .tag = tag, |
| 5332 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 5333 | | // .reg1 = switch (ty.tag()) { |
| 5334 | | // .f32 => .esp, |
| 5335 | | // .f64 => .rsp, |
| 5336 | | // else => unreachable, |
| 5337 | | // }, |
| 5338 | | // .reg2 = reg.to128(), |
| 5339 | | // .flags = 0b01, |
| 5340 | | // }), |
| 5341 | | // .data = .{ .disp = -stack_offset }, |
| 5342 | | // }); |
| 5343 | | return; |
| 5317 | // TODO verify this |
| 5318 | const ptr_size: Memory.PtrSize = switch (ty.tag()) { |
| 5319 | .f32 => .dword, |
| 5320 | .f64 => .qword, |
| 5321 | else => unreachable, |
| 5322 | }; |
| 5323 | return self.asmMemoryRegister(tag, Memory.sib(ptr_size, .{ |
| 5324 | .base = .rsp, |
| 5325 | .disp = -stack_offset, |
| 5326 | }), reg.to128()); |
| 5344 | 5327 | } |
| 5345 | 5328 | |
| 5346 | 5329 | return self.fail("TODO genSetStackArg for register with no intrinsics", .{}); |
| 5347 | 5330 | }, |
| 5348 | 5331 | else => { |
| 5349 | | // _ = try self.addInst(.{ |
| 5350 | | // .tag = .mov, |
| 5351 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 5352 | | // .reg1 = .rsp, |
| 5353 | | // .reg2 = registerAlias(reg, @intCast(u32, abi_size)), |
| 5354 | | // .flags = 0b10, |
| 5355 | | // }), |
| 5356 | | // .data = .{ .disp = -stack_offset }, |
| 5357 | | // }); |
| 5332 | try self.asmMemoryRegister(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 5333 | .base = .rsp, |
| 5334 | .disp = -stack_offset, |
| 5335 | }), registerAlias(reg, abi_size)); |
| 5358 | 5336 | }, |
| 5359 | 5337 | } |
| 5360 | 5338 | }, |
| ... | ... | @@ -5507,25 +5485,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5507 | 5485 | switch (ty.zigTypeTag()) { |
| 5508 | 5486 | .Float => { |
| 5509 | 5487 | if (intrinsicsAllowed(self.target.*, ty)) { |
| 5510 | | // const tag: Mir.Inst.Tag = switch (ty.tag()) { |
| 5511 | | // .f32 => Mir.Inst.Tag.mov_f32, |
| 5512 | | // .f64 => Mir.Inst.Tag.mov_f64, |
| 5513 | | // else => return self.fail("TODO genSetStack for register for type {}", .{ty.fmtDebug()}), |
| 5514 | | // }; |
| 5515 | | // _ = try self.addInst(.{ |
| 5516 | | // .tag = tag, |
| 5517 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 5518 | | // .reg1 = switch (ty.tag()) { |
| 5519 | | // .f32 => base_reg.to32(), |
| 5520 | | // .f64 => base_reg.to64(), |
| 5521 | | // else => unreachable, |
| 5522 | | // }, |
| 5523 | | // .reg2 = reg.to128(), |
| 5524 | | // .flags = 0b01, |
| 5525 | | // }), |
| 5526 | | // .data = .{ .disp = -stack_offset }, |
| 5527 | | // }); |
| 5528 | | return; |
| 5488 | const tag: Mir.Inst.Tag = switch (ty.tag()) { |
| 5489 | .f32 => .movss, |
| 5490 | .f64 => .movsd, |
| 5491 | else => return self.fail( |
| 5492 | "TODO genSetStack for register for type {}", |
| 5493 | .{ty.fmtDebug()}, |
| 5494 | ), |
| 5495 | }; |
| 5496 | const ptr_size: Memory.PtrSize = switch (ty.tag()) { |
| 5497 | .f32 => .dword, |
| 5498 | .f64 => .qword, |
| 5499 | else => unreachable, |
| 5500 | }; |
| 5501 | return self.asmMemoryRegister(tag, Memory.sib(ptr_size, .{ |
| 5502 | .base = base_reg.to64(), |
| 5503 | .disp = -stack_offset, |
| 5504 | }), reg.to128()); |
| 5529 | 5505 | } |
| 5530 | 5506 | |
| 5531 | 5507 | return self.fail("TODO genSetStack for register for type float with no intrinsics", .{}); |
| ... | ... | @@ -5590,16 +5566,10 @@ fn genInlineMemcpyRegisterRegister( |
| 5590 | 5566 | var remainder = abi_size; |
| 5591 | 5567 | while (remainder > 0) { |
| 5592 | 5568 | const nearest_power_of_two = @as(u6, 1) << math.log2_int(u3, @intCast(u3, remainder)); |
| 5593 | | |
| 5594 | | // _ = try self.addInst(.{ |
| 5595 | | // .tag = .mov, |
| 5596 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 5597 | | // .reg1 = dst_reg, |
| 5598 | | // .reg2 = registerAlias(tmp_reg, nearest_power_of_two), |
| 5599 | | // .flags = 0b10, |
| 5600 | | // }), |
| 5601 | | // .data = .{ .disp = -next_offset }, |
| 5602 | | // }); |
| 5569 | try self.asmMemoryRegister(.mov, Memory.sib(Memory.PtrSize.fromSize(nearest_power_of_two), .{ |
| 5570 | .base = dst_reg, |
| 5571 | .disp = -next_offset, |
| 5572 | }), registerAlias(tmp_reg, nearest_power_of_two)); |
| 5603 | 5573 | |
| 5604 | 5574 | if (nearest_power_of_two > 1) { |
| 5605 | 5575 | try self.genShiftBinOpMir(.shr, ty, tmp_reg, .{ |
| ... | ... | @@ -5611,15 +5581,10 @@ fn genInlineMemcpyRegisterRegister( |
| 5611 | 5581 | next_offset -= nearest_power_of_two; |
| 5612 | 5582 | } |
| 5613 | 5583 | } else { |
| 5614 | | // _ = try self.addInst(.{ |
| 5615 | | // .tag = .mov, |
| 5616 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 5617 | | // .reg1 = dst_reg, |
| 5618 | | // .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)), |
| 5619 | | // .flags = 0b10, |
| 5620 | | // }), |
| 5621 | | // .data = .{ .disp = -offset }, |
| 5622 | | // }); |
| 5584 | try self.asmMemoryRegister(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 5585 | .base = dst_reg, |
| 5586 | .disp = -offset, |
| 5587 | }), registerAlias(src_reg, abi_size)); |
| 5623 | 5588 | } |
| 5624 | 5589 | } |
| 5625 | 5590 | |
| ... | ... | @@ -5660,15 +5625,10 @@ fn genInlineMemcpy( |
| 5660 | 5625 | try self.loadMemPtrIntoRegister(dst_addr_reg, Type.usize, dst_ptr); |
| 5661 | 5626 | }, |
| 5662 | 5627 | .ptr_stack_offset, .stack_offset => |off| { |
| 5663 | | _ = off; |
| 5664 | | // _ = try self.addInst(.{ |
| 5665 | | // .tag = .lea, |
| 5666 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 5667 | | // .reg1 = dst_addr_reg.to64(), |
| 5668 | | // .reg2 = opts.dest_stack_base orelse .rbp, |
| 5669 | | // }), |
| 5670 | | // .data = .{ .disp = -off }, |
| 5671 | | // }); |
| 5628 | try self.asmRegisterMemory(.lea, dst_addr_reg.to64(), Memory.sib(.qword, .{ |
| 5629 | .base = opts.dest_stack_base orelse .rbp, |
| 5630 | .disp = -off, |
| 5631 | })); |
| 5672 | 5632 | }, |
| 5673 | 5633 | .register => |reg| { |
| 5674 | 5634 | try self.asmRegisterRegister( |
| ... | ... | @@ -5754,7 +5714,7 @@ fn genInlineMemcpy( |
| 5754 | 5714 | try self.asmRegisterImmediate(.sub, count_reg, Immediate.u(1)); |
| 5755 | 5715 | |
| 5756 | 5716 | _ = try self.addInst(.{ |
| 5757 | | .tag = .jmp, |
| 5717 | .tag = .jmp_reloc, |
| 5758 | 5718 | .ops = .inst, |
| 5759 | 5719 | .data = .{ .inst = loop_start }, |
| 5760 | 5720 | }); |
| ... | ... | @@ -5857,7 +5817,7 @@ fn genInlineMemset( |
| 5857 | 5817 | try self.asmRegisterImmediate(.sub, index_reg, Immediate.u(1)); |
| 5858 | 5818 | |
| 5859 | 5819 | _ = try self.addInst(.{ |
| 5860 | | .tag = .jmp, |
| 5820 | .tag = .jmp_reloc, |
| 5861 | 5821 | .ops = .inst, |
| 5862 | 5822 | .data = .{ .inst = loop_start }, |
| 5863 | 5823 | }); |
| ... | ... | @@ -6045,19 +6005,20 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6045 | 6005 | // .data = .{ .disp = @intCast(i32, x) }, |
| 6046 | 6006 | // }); |
| 6047 | 6007 | } else { |
| 6048 | | // If this is RAX, we can use a direct load. |
| 6049 | | // Otherwise, we need to load the address, then indirectly load the value. |
| 6050 | 6008 | if (reg.to64() == .rax) { |
| 6051 | | // movabs rax, ds:moffs64 |
| 6052 | | // const payload = try self.addExtra(Mir.Imm64.encode(x)); |
| 6053 | | // _ = try self.addInst(.{ |
| 6054 | | // .tag = .movabs, |
| 6055 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 6056 | | // .reg1 = .rax, |
| 6057 | | // .flags = 0b01, // imm64 will become moffs64 |
| 6058 | | // }), |
| 6059 | | // .data = .{ .payload = payload }, |
| 6060 | | // }); |
| 6009 | // If this is RAX, we can use a direct load. |
| 6010 | // Otherwise, we need to load the address, then indirectly load the value. |
| 6011 | var moffs: Mir.MemoryMoffs = .{ |
| 6012 | .seg = @enumToInt(Register.ds), |
| 6013 | .msb = undefined, |
| 6014 | .lsb = undefined, |
| 6015 | }; |
| 6016 | moffs.encodeOffset(x); |
| 6017 | _ = try self.addInst(.{ |
| 6018 | .tag = .mov_moffs, |
| 6019 | .ops = .rax_moffs, |
| 6020 | .data = .{ .payload = try self.addExtra(moffs) }, |
| 6021 | }); |
| 6061 | 6022 | } else { |
| 6062 | 6023 | // Rather than duplicate the logic used for the move, we just use a self-call with a new MCValue. |
| 6063 | 6024 | try self.genSetReg(ty, reg, MCValue{ .immediate = x }); |