diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-09 09:38:59 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-11 20:05:49 +0100 |
| commit | f61a70e812b0301f4e54e38ff4ce2b041f395e8d (patch) | |
| tree | 6da2945145d580f4df1c868e4e6c1bffc72e2a20 /src | |
| parent | aa8fda799e64c02d44fe80d1297b5ec8ae6b7677 (diff) | |
| download | zig-f61a70e812b0301f4e54e38ff4ce2b041f395e8d.tar.gz zig-f61a70e812b0301f4e54e38ff4ce2b041f395e8d.zip | |
x86_64: handle encoding and decoding Imm64 unsigned
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 37 | ||||
| -rw-r--r-- | src/arch/x86_64/Emit.zig | 8 |
2 files changed, 24 insertions, 21 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 6dacbadd8f..d6dd63ee57 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -417,7 +417,6 @@ fn asmRegister(self: *Self, tag: Mir.Inst.Tag, reg: Register) !void { } fn asmImmediate(self: *Self, tag: Mir.Inst.Tag, imm: Immediate) !void { - // TODO imm64 const ops: Mir.Inst.Ops = if (imm == .signed) .imm_s else .imm_u; const data: Mir.Inst.Data = switch (ops) { .imm_s => .{ .imm_s = imm.signed }, @@ -443,7 +442,10 @@ fn asmRegisterRegister(self: *Self, tag: Mir.Inst.Tag, reg1: Register, reg2: Reg } fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Immediate) !void { - const ops: Mir.Inst.Ops = if (imm == .signed) .ri_s else .ri_u; + const ops: Mir.Inst.Ops = switch (imm) { + .signed => .ri_s, + .unsigned => |x| if (x <= math.maxInt(u32)) .ri_u else .ri64, + }; const data: Mir.Inst.Data = switch (ops) { .ri_s => .{ .ri_s = .{ .r1 = reg, @@ -453,6 +455,10 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Imme .r1 = reg, .imm = @intCast(u32, imm.unsigned), } }, + .ri64 => .{ .rx = .{ + .r1 = reg, + .payload = try self.addExtra(Mir.Imm64.encode(imm.unsigned)), + } }, else => unreachable, }; _ = try self.addInst(.{ @@ -6118,32 +6124,23 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void // }); }, .immediate => |x| { - // 32-bit moves zero-extend to 64-bit, so xoring the 32-bit - // register is the fastest way to zero a register. if (x == 0) { + // 32-bit moves zero-extend to 64-bit, so xoring the 32-bit + // register is the fastest way to zero a register. return self.asmRegisterRegister(.xor, reg.to32(), reg.to32()); } - if (x <= math.maxInt(i32)) { - // Next best case: if we set the lower four bytes, the upper four will be zeroed. + if (ty.isSignedInt() and x <= math.maxInt(i32)) { return self.asmRegisterImmediate( .mov, registerAlias(reg, abi_size), - Immediate.u(@intCast(u32, x)), + Immediate.s(@intCast(i32, @bitCast(i64, x))), ); } - // Worst case: we need to load the 64-bit register with the IMM. GNU's assemblers calls - // this `movabs`, though this is officially just a different variant of the plain `mov` - // instruction. - // - // This encoding is, in fact, the *same* as the one used for 32-bit loads. The only - // difference is that we set REX.W before the instruction, which extends the load to - // 64-bit and uses the full bit-width of the register. - // const payload = try self.addExtra(Mir.Imm64.encode(x)); - // _ = try self.addInst(.{ - // .tag = .movabs, - // .ops = Mir.Inst.Ops.encode(.{ .reg1 = reg.to64() }), - // .data = .{ .payload = payload }, - // }); + return self.asmRegisterImmediate( + .mov, + registerAlias(reg, abi_size), + Immediate.u(x), + ); }, .register => |src_reg| { // If the registers are the same, nothing to do. diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig index 15f41a943c..35b8b59846 100644 --- a/src/arch/x86_64/Emit.zig +++ b/src/arch/x86_64/Emit.zig @@ -178,9 +178,10 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE if (mem.eql(u8, field.name, @tagName(tag))) break @field(Instruction.Mnemonic, field.name); } else unreachable; - var operands = [4]Instruction.Operand{ .none, .none, .none, .none }; const ops = emit.mir.instructions.items(.ops)[inst]; const data = emit.mir.instructions.items(.data)[inst]; + + var operands = [4]Instruction.Operand{ .none, .none, .none, .none }; switch (ops) { .none => {}, .imm_s => operands[0] = .{ .imm = Immediate.s(data.imm_s) }, @@ -198,6 +199,11 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE .{ .reg = data.ri_u.r1 }, .{ .imm = Immediate.u(data.ri_u.imm) }, }, + .ri64 => { + operands[0] = .{ .reg = data.rx.r1 }; + const imm64 = emit.mir.extraData(Mir.Imm64, data.rx.payload).data; + operands[1] = .{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) }; + }, else => unreachable, } |
