| ... | ... | @@ -417,7 +417,6 @@ fn asmRegister(self: *Self, tag: Mir.Inst.Tag, reg: Register) !void { |
| 417 | 417 | } |
| 418 | 418 | |
| 419 | 419 | fn asmImmediate(self: *Self, tag: Mir.Inst.Tag, imm: Immediate) !void { |
| 420 | | // TODO imm64 |
| 421 | 420 | const ops: Mir.Inst.Ops = if (imm == .signed) .imm_s else .imm_u; |
| 422 | 421 | const data: Mir.Inst.Data = switch (ops) { |
| 423 | 422 | .imm_s => .{ .imm_s = imm.signed }, |
| ... | ... | @@ -443,7 +442,10 @@ fn asmRegisterRegister(self: *Self, tag: Mir.Inst.Tag, reg1: Register, reg2: Reg |
| 443 | 442 | } |
| 444 | 443 | |
| 445 | 444 | fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Immediate) !void { |
| 446 | | const ops: Mir.Inst.Ops = if (imm == .signed) .ri_s else .ri_u; |
| 445 | const ops: Mir.Inst.Ops = switch (imm) { |
| 446 | .signed => .ri_s, |
| 447 | .unsigned => |x| if (x <= math.maxInt(u32)) .ri_u else .ri64, |
| 448 | }; |
| 447 | 449 | const data: Mir.Inst.Data = switch (ops) { |
| 448 | 450 | .ri_s => .{ .ri_s = .{ |
| 449 | 451 | .r1 = reg, |
| ... | ... | @@ -453,6 +455,10 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Imme |
| 453 | 455 | .r1 = reg, |
| 454 | 456 | .imm = @intCast(u32, imm.unsigned), |
| 455 | 457 | } }, |
| 458 | .ri64 => .{ .rx = .{ |
| 459 | .r1 = reg, |
| 460 | .payload = try self.addExtra(Mir.Imm64.encode(imm.unsigned)), |
| 461 | } }, |
| 456 | 462 | else => unreachable, |
| 457 | 463 | }; |
| 458 | 464 | _ = try self.addInst(.{ |
| ... | ... | @@ -6118,32 +6124,23 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6118 | 6124 | // }); |
| 6119 | 6125 | }, |
| 6120 | 6126 | .immediate => |x| { |
| 6121 | | // 32-bit moves zero-extend to 64-bit, so xoring the 32-bit |
| 6122 | | // register is the fastest way to zero a register. |
| 6123 | 6127 | if (x == 0) { |
| 6128 | // 32-bit moves zero-extend to 64-bit, so xoring the 32-bit |
| 6129 | // register is the fastest way to zero a register. |
| 6124 | 6130 | return self.asmRegisterRegister(.xor, reg.to32(), reg.to32()); |
| 6125 | 6131 | } |
| 6126 | | if (x <= math.maxInt(i32)) { |
| 6127 | | // Next best case: if we set the lower four bytes, the upper four will be zeroed. |
| 6132 | if (ty.isSignedInt() and x <= math.maxInt(i32)) { |
| 6128 | 6133 | return self.asmRegisterImmediate( |
| 6129 | 6134 | .mov, |
| 6130 | 6135 | registerAlias(reg, abi_size), |
| 6131 | | Immediate.u(@intCast(u32, x)), |
| 6136 | Immediate.s(@intCast(i32, @bitCast(i64, x))), |
| 6132 | 6137 | ); |
| 6133 | 6138 | } |
| 6134 | | // Worst case: we need to load the 64-bit register with the IMM. GNU's assemblers calls |
| 6135 | | // this `movabs`, though this is officially just a different variant of the plain `mov` |
| 6136 | | // instruction. |
| 6137 | | // |
| 6138 | | // This encoding is, in fact, the *same* as the one used for 32-bit loads. The only |
| 6139 | | // difference is that we set REX.W before the instruction, which extends the load to |
| 6140 | | // 64-bit and uses the full bit-width of the register. |
| 6141 | | // const payload = try self.addExtra(Mir.Imm64.encode(x)); |
| 6142 | | // _ = try self.addInst(.{ |
| 6143 | | // .tag = .movabs, |
| 6144 | | // .ops = Mir.Inst.Ops.encode(.{ .reg1 = reg.to64() }), |
| 6145 | | // .data = .{ .payload = payload }, |
| 6146 | | // }); |
| 6139 | return self.asmRegisterImmediate( |
| 6140 | .mov, |
| 6141 | registerAlias(reg, abi_size), |
| 6142 | Immediate.u(x), |
| 6143 | ); |
| 6147 | 6144 | }, |
| 6148 | 6145 | .register => |src_reg| { |
| 6149 | 6146 | // If the registers are the same, nothing to do. |