| ... | ... | @@ -509,6 +509,29 @@ fn asmMemory(self: *Self, tag: Mir.Inst.Tag, m: Memory) !void { |
| 509 | 509 | }); |
| 510 | 510 | } |
| 511 | 511 | |
| 512 | fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.Tag, m: Memory, imm: Immediate) !void { |
| 513 | const ops: Mir.Inst.Ops = switch (m) { |
| 514 | .sib => if (imm == .signed) .mi_s_sib else .mi_u_sib, |
| 515 | .rip => if (imm == .signed) .mi_s_rip else .mi_u_rip, |
| 516 | else => unreachable, |
| 517 | }; |
| 518 | const payload: u32 = switch (ops) { |
| 519 | .mi_s_sib, .mi_u_sib => try self.addExtra(Mir.MemorySib.encode(m)), |
| 520 | .mi_s_rip, .mi_u_rip => try self.addExtra(Mir.MemoryRip.encode(m)), |
| 521 | else => unreachable, |
| 522 | }; |
| 523 | const data: Mir.Inst.Data = switch (ops) { |
| 524 | .mi_s_sib, .mi_s_rip => .{ .xi_s = .{ .imm = imm.signed, .payload = payload } }, |
| 525 | .mi_u_sib, .mi_u_rip => .{ .xi_u = .{ .imm = @intCast(u32, imm.unsigned), .payload = payload } }, |
| 526 | else => unreachable, |
| 527 | }; |
| 528 | _ = try self.addInst(.{ |
| 529 | .tag = tag, |
| 530 | .ops = ops, |
| 531 | .data = data, |
| 532 | }); |
| 533 | } |
| 534 | |
| 512 | 535 | fn asmRegisterMemory(self: *Self, tag: Mir.Inst.Tag, reg: Register, m: Memory) !void { |
| 513 | 536 | const ops: Mir.Inst.Ops = switch (m) { |
| 514 | 537 | .sib => .rm_sib, |
| ... | ... | @@ -2776,7 +2799,7 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue |
| 2776 | 2799 | } |
| 2777 | 2800 | |
| 2778 | 2801 | fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void { |
| 2779 | | const abi_size = value_ty.abiSize(self.target.*); |
| 2802 | const abi_size = @intCast(u32, value_ty.abiSize(self.target.*)); |
| 2780 | 2803 | switch (ptr) { |
| 2781 | 2804 | .none => unreachable, |
| 2782 | 2805 | .undef => unreachable, |
| ... | ... | @@ -2807,28 +2830,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2807 | 2830 | try self.genSetReg(value_ty, reg, value); |
| 2808 | 2831 | }, |
| 2809 | 2832 | .immediate => |imm| { |
| 2810 | | _ = imm; |
| 2811 | 2833 | switch (abi_size) { |
| 2812 | 2834 | 1, 2, 4 => { |
| 2813 | | // TODO this is wasteful! |
| 2814 | | // introduce new MIR tag specifically for mov [reg + 0], imm |
| 2815 | | // const payload = try self.addExtra(Mir.ImmPair{ |
| 2816 | | // .dest_off = 0, |
| 2817 | | // .operand = @truncate(u32, imm), |
| 2818 | | // }); |
| 2819 | | // _ = try self.addInst(.{ |
| 2820 | | // .tag = .mov_mem_imm, |
| 2821 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 2822 | | // .reg1 = reg.to64(), |
| 2823 | | // .flags = switch (abi_size) { |
| 2824 | | // 1 => 0b00, |
| 2825 | | // 2 => 0b01, |
| 2826 | | // 4 => 0b10, |
| 2827 | | // else => unreachable, |
| 2828 | | // }, |
| 2829 | | // }), |
| 2830 | | // .data = .{ .payload = payload }, |
| 2831 | | // }); |
| 2835 | try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 2836 | .base = reg.to64(), |
| 2837 | .disp = 0, |
| 2838 | }), Immediate.u(@truncate(u32, imm))); |
| 2832 | 2839 | }, |
| 2833 | 2840 | 8 => { |
| 2834 | 2841 | // TODO: optimization: if the imm is only using the lower |
| ... | ... | @@ -2913,19 +2920,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2913 | 2920 | return self.fail("TODO saving imm to memory for abi_size {}", .{abi_size}); |
| 2914 | 2921 | } |
| 2915 | 2922 | |
| 2916 | | // const payload = try self.addExtra(Mir.ImmPair{ |
| 2917 | | // .dest_off = 0, |
| 2918 | | // // TODO check if this logic is correct |
| 2919 | | // .operand = @intCast(u32, imm), |
| 2920 | | // }); |
| 2921 | | const flags: u2 = switch (abi_size) { |
| 2922 | | 1 => 0b00, |
| 2923 | | 2 => 0b01, |
| 2924 | | 4 => 0b10, |
| 2925 | | 8 => 0b11, |
| 2926 | | else => unreachable, |
| 2927 | | }; |
| 2928 | | if (flags == 0b11) { |
| 2923 | if (abi_size == 8) { |
| 2924 | // TODO |
| 2929 | 2925 | const top_bits: u32 = @intCast(u32, imm >> 32); |
| 2930 | 2926 | const can_extend = if (value_ty.isUnsignedInt()) |
| 2931 | 2927 | (top_bits == 0) and (imm & 0x8000_0000) == 0 |
| ... | ... | @@ -2936,14 +2932,10 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2936 | 2932 | return self.fail("TODO imm64 would get incorrectly sign extended", .{}); |
| 2937 | 2933 | } |
| 2938 | 2934 | } |
| 2939 | | // _ = try self.addInst(.{ |
| 2940 | | // .tag = .mov_mem_imm, |
| 2941 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 2942 | | // .reg1 = addr_reg.to64(), |
| 2943 | | // .flags = flags, |
| 2944 | | // }), |
| 2945 | | // .data = .{ .payload = payload }, |
| 2946 | | // }); |
| 2935 | try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 2936 | .base = addr_reg.to64(), |
| 2937 | .disp = 0, |
| 2938 | }), Immediate.u(@intCast(u32, imm))); |
| 2947 | 2939 | }, |
| 2948 | 2940 | .register => { |
| 2949 | 2941 | return self.store(new_ptr, value, ptr_ty, value_ty); |
| ... | ... | @@ -3595,12 +3587,12 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3595 | 3587 | ), |
| 3596 | 3588 | }, |
| 3597 | 3589 | .immediate => |imm| { |
| 3598 | | _ = imm; |
| 3599 | | // _ = try self.addInst(.{ |
| 3600 | | // .tag = mir_tag, |
| 3601 | | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = registerAlias(dst_reg, abi_size) }), |
| 3602 | | // .data = .{ .imm = @intCast(u32, imm) }, |
| 3603 | | // }); |
| 3590 | // TODO |
| 3591 | try self.asmRegisterImmediate( |
| 3592 | mir_tag, |
| 3593 | registerAlias(dst_reg, abi_size), |
| 3594 | Immediate.u(@intCast(u32, imm)), |
| 3595 | ); |
| 3604 | 3596 | }, |
| 3605 | 3597 | .memory, |
| 3606 | 3598 | .linker_load, |
| ... | ... | @@ -3645,36 +3637,11 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MCValu |
| 3645 | 3637 | }), registerAlias(src_reg, abi_size)); |
| 3646 | 3638 | }, |
| 3647 | 3639 | .immediate => |imm| { |
| 3648 | | _ = imm; |
| 3649 | | // const tag: Mir.Inst.Tag = switch (mir_tag) { |
| 3650 | | // .add => .add_mem_imm, |
| 3651 | | // .@"or" => .or_mem_imm, |
| 3652 | | // .@"and" => .and_mem_imm, |
| 3653 | | // .sub => .sub_mem_imm, |
| 3654 | | // .xor => .xor_mem_imm, |
| 3655 | | // .cmp => .cmp_mem_imm, |
| 3656 | | // else => unreachable, |
| 3657 | | // }; |
| 3658 | | const flags: u2 = switch (abi_size) { |
| 3659 | | 1 => 0b00, |
| 3660 | | 2 => 0b01, |
| 3661 | | 4 => 0b10, |
| 3662 | | 8 => 0b11, |
| 3663 | | else => unreachable, |
| 3664 | | }; |
| 3665 | | // const payload = try self.addExtra(Mir.ImmPair{ |
| 3666 | | // .dest_off = -off, |
| 3667 | | // .operand = @intCast(u32, imm), |
| 3668 | | // }); |
| 3669 | | _ = flags; |
| 3670 | | // _ = try self.addInst(.{ |
| 3671 | | // .tag = tag, |
| 3672 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 3673 | | // .reg1 = .rbp, |
| 3674 | | // .flags = flags, |
| 3675 | | // }), |
| 3676 | | // .data = .{ .payload = payload }, |
| 3677 | | // }); |
| 3640 | // TODO |
| 3641 | try self.asmMemoryImmediate(mir_tag, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 3642 | .base = .rbp, |
| 3643 | .disp = -off, |
| 3644 | }), Immediate.u(@intCast(u32, imm))); |
| 3678 | 3645 | }, |
| 3679 | 3646 | .memory, |
| 3680 | 3647 | .stack_offset, |
| ... | ... | @@ -5258,33 +5225,18 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 5258 | 5225 | return self.genSetStackArg(ty, stack_offset, .{ .register = reg }); |
| 5259 | 5226 | }, |
| 5260 | 5227 | .immediate => |imm| { |
| 5261 | | _ = imm; |
| 5262 | 5228 | switch (abi_size) { |
| 5263 | | // TODO |
| 5264 | | // 1, 2, 4 => { |
| 5265 | | // // We have a positive stack offset value but we want a twos complement negative |
| 5266 | | // // offset from rbp, which is at the top of the stack frame. |
| 5267 | | // // mov [rbp+offset], immediate |
| 5268 | | // const flags: u2 = switch (abi_size) { |
| 5269 | | // 1 => 0b00, |
| 5270 | | // 2 => 0b01, |
| 5271 | | // 4 => 0b10, |
| 5272 | | // else => unreachable, |
| 5273 | | // }; |
| 5274 | | // const payload = try self.addExtra(Mir.ImmPair{ |
| 5275 | | // .dest_off = -stack_offset, |
| 5276 | | // .operand = @intCast(u32, imm), |
| 5277 | | // }); |
| 5278 | | // _ = try self.addInst(.{ |
| 5279 | | // .tag = .mov_mem_imm, |
| 5280 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 5281 | | // .reg1 = .rsp, |
| 5282 | | // .flags = flags, |
| 5283 | | // }), |
| 5284 | | // .data = .{ .payload = payload }, |
| 5285 | | // }); |
| 5286 | | // }, |
| 5287 | | 1, 2, 4, 8 => { |
| 5229 | 1, 2, 4 => { |
| 5230 | // TODO |
| 5231 | // We have a positive stack offset value but we want a twos complement negative |
| 5232 | // offset from rbp, which is at the top of the stack frame. |
| 5233 | // mov [rbp+offset], immediate |
| 5234 | try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 5235 | .base = .rsp, |
| 5236 | .disp = -stack_offset, |
| 5237 | }), Immediate.u(@intCast(u32, imm))); |
| 5238 | }, |
| 5239 | 8 => { |
| 5288 | 5240 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 5289 | 5241 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); |
| 5290 | 5242 | }, |
| ... | ... | @@ -5355,7 +5307,7 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 5355 | 5307 | } |
| 5356 | 5308 | |
| 5357 | 5309 | fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: InlineMemcpyOpts) InnerError!void { |
| 5358 | | const abi_size = ty.abiSize(self.target.*); |
| 5310 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 5359 | 5311 | switch (mcv) { |
| 5360 | 5312 | .dead => unreachable, |
| 5361 | 5313 | .unreach, .none => return, // Nothing to do. |
| ... | ... | @@ -5400,75 +5352,33 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5400 | 5352 | return self.genSetStack(ty, stack_offset, .{ .register = reg }, opts); |
| 5401 | 5353 | }, |
| 5402 | 5354 | .immediate => |x_big| { |
| 5403 | | _ = x_big; |
| 5404 | 5355 | const base_reg = opts.dest_stack_base orelse .rbp; |
| 5405 | | _ = base_reg; |
| 5356 | // TODO |
| 5406 | 5357 | switch (abi_size) { |
| 5407 | 5358 | 0 => { |
| 5408 | 5359 | assert(ty.isError()); |
| 5409 | | // const payload = try self.addExtra(Mir.ImmPair{ |
| 5410 | | // .dest_off = -stack_offset, |
| 5411 | | // .operand = @truncate(u32, x_big), |
| 5412 | | // }); |
| 5413 | | // _ = try self.addInst(.{ |
| 5414 | | // .tag = .mov_mem_imm, |
| 5415 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 5416 | | // .reg1 = base_reg, |
| 5417 | | // .flags = 0b00, |
| 5418 | | // }), |
| 5419 | | // .data = .{ .payload = payload }, |
| 5420 | | // }); |
| 5360 | try self.asmMemoryImmediate(.mov, Memory.sib(.byte, .{ |
| 5361 | .base = base_reg, |
| 5362 | .disp = -stack_offset, |
| 5363 | }), Immediate.u(@truncate(u32, x_big))); |
| 5421 | 5364 | }, |
| 5422 | 5365 | 1, 2, 4 => { |
| 5423 | | // const payload = try self.addExtra(Mir.ImmPair{ |
| 5424 | | // .dest_off = -stack_offset, |
| 5425 | | // .operand = @truncate(u32, x_big), |
| 5426 | | // }); |
| 5427 | | // _ = try self.addInst(.{ |
| 5428 | | // .tag = .mov_mem_imm, |
| 5429 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 5430 | | // .reg1 = base_reg, |
| 5431 | | // .flags = switch (abi_size) { |
| 5432 | | // 1 => 0b00, |
| 5433 | | // 2 => 0b01, |
| 5434 | | // 4 => 0b10, |
| 5435 | | // else => unreachable, |
| 5436 | | // }, |
| 5437 | | // }), |
| 5438 | | // .data = .{ .payload = payload }, |
| 5439 | | // }); |
| 5366 | try self.asmMemoryImmediate(.mov, Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 5367 | .base = base_reg, |
| 5368 | .disp = -stack_offset, |
| 5369 | }), Immediate.u(@truncate(u32, x_big))); |
| 5440 | 5370 | }, |
| 5441 | 5371 | 8 => { |
| 5442 | 5372 | // 64 bit write to memory would take two mov's anyways so we |
| 5443 | 5373 | // insted just use two 32 bit writes to avoid register allocation |
| 5444 | | { |
| 5445 | | // const payload = try self.addExtra(Mir.ImmPair{ |
| 5446 | | // .dest_off = -stack_offset + 4, |
| 5447 | | // .operand = @truncate(u32, x_big >> 32), |
| 5448 | | // }); |
| 5449 | | // _ = try self.addInst(.{ |
| 5450 | | // .tag = .mov_mem_imm, |
| 5451 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 5452 | | // .reg1 = base_reg, |
| 5453 | | // .flags = 0b10, |
| 5454 | | // }), |
| 5455 | | // .data = .{ .payload = payload }, |
| 5456 | | // }); |
| 5457 | | } |
| 5458 | | { |
| 5459 | | // const payload = try self.addExtra(Mir.ImmPair{ |
| 5460 | | // .dest_off = -stack_offset, |
| 5461 | | // .operand = @truncate(u32, x_big), |
| 5462 | | // }); |
| 5463 | | // _ = try self.addInst(.{ |
| 5464 | | // .tag = .mov_mem_imm, |
| 5465 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 5466 | | // .reg1 = base_reg, |
| 5467 | | // .flags = 0b10, |
| 5468 | | // }), |
| 5469 | | // .data = .{ .payload = payload }, |
| 5470 | | // }); |
| 5471 | | } |
| 5374 | try self.asmMemoryImmediate(.mov, Memory.sib(.dword, .{ |
| 5375 | .base = base_reg, |
| 5376 | .disp = -stack_offset + 4, |
| 5377 | }), Immediate.u(@truncate(u32, x_big >> 32))); |
| 5378 | try self.asmMemoryImmediate(.mov, Memory.sib(.dword, .{ |
| 5379 | .base = base_reg, |
| 5380 | .disp = -stack_offset, |
| 5381 | }), Immediate.u(@truncate(u32, x_big))); |
| 5472 | 5382 | }, |
| 5473 | 5383 | else => { |
| 5474 | 5384 | return self.fail("TODO implement set abi_size=large stack variable with immediate", .{}); |
| ... | ... | @@ -5647,15 +5557,10 @@ fn genInlineMemcpy( |
| 5647 | 5557 | try self.loadMemPtrIntoRegister(src_addr_reg, Type.usize, src_ptr); |
| 5648 | 5558 | }, |
| 5649 | 5559 | .ptr_stack_offset, .stack_offset => |off| { |
| 5650 | | _ = off; |
| 5651 | | // _ = try self.addInst(.{ |
| 5652 | | // .tag = .lea, |
| 5653 | | // .ops = Mir.Inst.Ops.encode(.{ |
| 5654 | | // .reg1 = src_addr_reg.to64(), |
| 5655 | | // .reg2 = opts.source_stack_base orelse .rbp, |
| 5656 | | // }), |
| 5657 | | // .data = .{ .disp = -off }, |
| 5658 | | // }); |
| 5560 | try self.asmRegisterMemory(.lea, src_addr_reg.to64(), Memory.sib(.qword, .{ |
| 5561 | .base = opts.source_stack_base orelse .rbp, |
| 5562 | .disp = -off, |
| 5563 | })); |
| 5659 | 5564 | }, |
| 5660 | 5565 | .register => |reg| { |
| 5661 | 5566 | try self.asmRegisterRegister( |