mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
x86_64: demolish the old
This commit is contained in:
parent
73a42953c9
commit
a1828ebcda
File diff suppressed because it is too large
Load Diff
@ -30,9 +30,10 @@ pub fn findByMnemonic(
|
||||
prefix: Instruction.Prefix,
|
||||
mnemonic: Mnemonic,
|
||||
ops: []const Instruction.Operand,
|
||||
target: *const std.Target,
|
||||
) !?Encoding {
|
||||
var input_ops = [1]Op{.none} ** 4;
|
||||
for (input_ops[0..ops.len], ops) |*input_op, op| input_op.* = Op.fromOperand(op);
|
||||
var input_ops: [4]Op = @splat(.none);
|
||||
for (input_ops[0..ops.len], ops) |*input_op, op| input_op.* = Op.fromOperand(op, target);
|
||||
|
||||
const rex_required = for (ops) |op| switch (op) {
|
||||
.reg => |r| switch (r) {
|
||||
@ -57,6 +58,16 @@ pub fn findByMnemonic(
|
||||
var shortest_enc: ?Encoding = null;
|
||||
var shortest_len: ?usize = null;
|
||||
next: for (mnemonic_to_encodings_map[@intFromEnum(mnemonic)]) |data| {
|
||||
if (!switch (data.feature) {
|
||||
.none => true,
|
||||
inline else => |tag| has_features: {
|
||||
comptime var feature_it = std.mem.splitScalar(u8, @tagName(tag), ' ');
|
||||
comptime var features: []const std.Target.x86.Feature = &.{};
|
||||
inline while (comptime feature_it.next()) |feature| features = features ++ .{@field(std.Target.x86.Feature, feature)};
|
||||
break :has_features std.Target.x86.featureSetHasAll(target.cpu.features, features[0..features.len].*);
|
||||
},
|
||||
}) continue;
|
||||
|
||||
switch (data.mode) {
|
||||
.none, .short => if (rex_required) continue,
|
||||
.rex, .rex_short => if (!rex_required) continue,
|
||||
@ -64,7 +75,7 @@ pub fn findByMnemonic(
|
||||
}
|
||||
for (input_ops, data.ops) |input_op, data_op| if (!input_op.isSubset(data_op)) continue :next;
|
||||
|
||||
const enc = Encoding{ .mnemonic = mnemonic, .data = data };
|
||||
const enc: Encoding = .{ .mnemonic = mnemonic, .data = data };
|
||||
if (shortest_enc) |previous_shortest_enc| {
|
||||
const len = estimateInstructionLength(prefix, enc, ops);
|
||||
const previous_shortest_len = shortest_len orelse
|
||||
@ -474,7 +485,7 @@ pub const Op = enum {
|
||||
ymm, ymm_m256,
|
||||
// zig fmt: on
|
||||
|
||||
pub fn fromOperand(operand: Instruction.Operand) Op {
|
||||
pub fn fromOperand(operand: Instruction.Operand, target: *const std.Target) Op {
|
||||
return switch (operand) {
|
||||
.none => .none,
|
||||
|
||||
@ -516,7 +527,7 @@ pub const Op = enum {
|
||||
|
||||
.mem => |mem| switch (mem) {
|
||||
.moffs => .moffs,
|
||||
.sib, .rip => switch (mem.bitSize()) {
|
||||
.sib, .rip => switch (mem.bitSize(target)) {
|
||||
0 => .m,
|
||||
8 => .m8,
|
||||
16 => .m16,
|
||||
@ -835,7 +846,7 @@ fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Op
|
||||
var inst = Instruction{
|
||||
.prefix = prefix,
|
||||
.encoding = encoding,
|
||||
.ops = [1]Operand{.none} ** 4,
|
||||
.ops = @splat(.none),
|
||||
};
|
||||
@memcpy(inst.ops[0..ops.len], ops);
|
||||
|
||||
@ -850,7 +861,7 @@ fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Op
|
||||
const mnemonic_to_encodings_map = init: {
|
||||
@setEvalBranchQuota(5_000);
|
||||
const mnemonic_count = @typeInfo(Mnemonic).@"enum".fields.len;
|
||||
var mnemonic_map: [mnemonic_count][]Data = .{&.{}} ** mnemonic_count;
|
||||
var mnemonic_map: [mnemonic_count][]Data = @splat(&.{});
|
||||
const encodings = @import("encodings.zig");
|
||||
for (encodings.table) |entry| mnemonic_map[@intFromEnum(entry[0])].len += 1;
|
||||
var data_storage: [encodings.table.len]Data = undefined;
|
||||
@ -859,7 +870,7 @@ const mnemonic_to_encodings_map = init: {
|
||||
value.ptr = data_storage[storage_i..].ptr;
|
||||
storage_i += value.len;
|
||||
}
|
||||
var mnemonic_i: [mnemonic_count]usize = .{0} ** mnemonic_count;
|
||||
var mnemonic_i: [mnemonic_count]usize = @splat(0);
|
||||
const ops_len = @typeInfo(std.meta.FieldType(Data, .ops)).array.len;
|
||||
const opc_len = @typeInfo(std.meta.FieldType(Data, .opc)).array.len;
|
||||
for (encodings.table) |entry| {
|
||||
@ -876,7 +887,7 @@ const mnemonic_to_encodings_map = init: {
|
||||
i.* += 1;
|
||||
}
|
||||
const final_storage = data_storage;
|
||||
var final_map: [mnemonic_count][]const Data = .{&.{}} ** mnemonic_count;
|
||||
var final_map: [mnemonic_count][]const Data = @splat(&.{});
|
||||
storage_i = 0;
|
||||
for (&final_map, mnemonic_map) |*final_value, value| {
|
||||
final_value.* = final_storage[storage_i..][0..value.len];
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! This file contains the functionality for lowering x86_64 MIR to Instructions
|
||||
|
||||
bin_file: *link.File,
|
||||
target: *const std.Target,
|
||||
output_mode: std.builtin.OutputMode,
|
||||
link_mode: std.builtin.LinkMode,
|
||||
pic: bool,
|
||||
@ -193,7 +194,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
|
||||
.pseudo_probe_align_ri_s => {
|
||||
try lower.emit(.none, .@"test", &.{
|
||||
.{ .reg = inst.data.ri.r1 },
|
||||
.{ .imm = Immediate.s(@bitCast(inst.data.ri.i)) },
|
||||
.{ .imm = .s(@bitCast(inst.data.ri.i)) },
|
||||
});
|
||||
try lower.emit(.none, .jz, &.{
|
||||
.{ .imm = lower.reloc(.{ .inst = index + 1 }, 0) },
|
||||
@ -229,14 +230,14 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
|
||||
}
|
||||
try lower.emit(.none, .sub, &.{
|
||||
.{ .reg = inst.data.ri.r1 },
|
||||
.{ .imm = Immediate.s(@bitCast(inst.data.ri.i)) },
|
||||
.{ .imm = .s(@bitCast(inst.data.ri.i)) },
|
||||
});
|
||||
assert(lower.result_insts_len <= pseudo_probe_adjust_unrolled_max_insts);
|
||||
},
|
||||
.pseudo_probe_adjust_setup_rri_s => {
|
||||
try lower.emit(.none, .mov, &.{
|
||||
.{ .reg = inst.data.rri.r2.to32() },
|
||||
.{ .imm = Immediate.s(@bitCast(inst.data.rri.i)) },
|
||||
.{ .imm = .s(@bitCast(inst.data.rri.i)) },
|
||||
});
|
||||
try lower.emit(.none, .sub, &.{
|
||||
.{ .reg = inst.data.rri.r1 },
|
||||
@ -255,7 +256,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
|
||||
});
|
||||
try lower.emit(.none, .sub, &.{
|
||||
.{ .reg = inst.data.rr.r2 },
|
||||
.{ .imm = Immediate.s(page_size) },
|
||||
.{ .imm = .s(page_size) },
|
||||
});
|
||||
try lower.emit(.none, .jae, &.{
|
||||
.{ .imm = lower.reloc(.{ .inst = index }, 0) },
|
||||
@ -355,7 +356,7 @@ pub fn imm(lower: Lower, ops: Mir.Inst.Ops, i: u32) Immediate {
|
||||
.mi_s,
|
||||
.rmi_s,
|
||||
.pseudo_dbg_local_ai_s,
|
||||
=> Immediate.s(@bitCast(i)),
|
||||
=> .s(@bitCast(i)),
|
||||
|
||||
.rrri,
|
||||
.rri_u,
|
||||
@ -368,11 +369,11 @@ pub fn imm(lower: Lower, ops: Mir.Inst.Ops, i: u32) Immediate {
|
||||
.rrm,
|
||||
.rrmi,
|
||||
.pseudo_dbg_local_ai_u,
|
||||
=> Immediate.u(i),
|
||||
=> .u(i),
|
||||
|
||||
.ri_64,
|
||||
.pseudo_dbg_local_ai_64,
|
||||
=> Immediate.u(lower.mir.extraData(Mir.Imm64, i).data.decode()),
|
||||
=> .u(lower.mir.extraData(Mir.Imm64, i).data.decode()),
|
||||
|
||||
else => unreachable,
|
||||
};
|
||||
@ -389,7 +390,7 @@ fn reloc(lower: *Lower, target: Reloc.Target, off: i32) Immediate {
|
||||
.off = off,
|
||||
};
|
||||
lower.result_relocs_len += 1;
|
||||
return Immediate.s(0);
|
||||
return .s(0);
|
||||
}
|
||||
|
||||
fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void {
|
||||
@ -421,15 +422,15 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
|
||||
try Instruction.new(.none, .lea, &[_]Operand{
|
||||
.{ .reg = .rdi },
|
||||
.{ .mem = Memory.initRip(mem_op.sib.ptr_size, 0) },
|
||||
});
|
||||
}, lower.target);
|
||||
lower.result_insts_len += 1;
|
||||
_ = lower.reloc(.{
|
||||
.linker_extern_fn = try elf_file.getGlobalSymbol("__tls_get_addr", null),
|
||||
}, 0);
|
||||
lower.result_insts[lower.result_insts_len] =
|
||||
try Instruction.new(.none, .call, &[_]Operand{
|
||||
.{ .imm = Immediate.s(0) },
|
||||
});
|
||||
.{ .imm = .s(0) },
|
||||
}, lower.target);
|
||||
lower.result_insts_len += 1;
|
||||
_ = lower.reloc(.{ .linker_dtpoff = sym_index }, 0);
|
||||
emit_mnemonic = .lea;
|
||||
@ -443,7 +444,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
|
||||
try Instruction.new(.none, .mov, &[_]Operand{
|
||||
.{ .reg = .rax },
|
||||
.{ .mem = Memory.initSib(.qword, .{ .base = .{ .reg = .fs } }) },
|
||||
});
|
||||
}, lower.target);
|
||||
lower.result_insts_len += 1;
|
||||
_ = lower.reloc(.{ .linker_reloc = sym_index }, 0);
|
||||
emit_mnemonic = .lea;
|
||||
@ -467,7 +468,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
|
||||
try Instruction.new(.none, .mov, &[_]Operand{
|
||||
.{ .reg = reg.to64() },
|
||||
.{ .mem = Memory.initRip(.qword, 0) },
|
||||
});
|
||||
}, lower.target);
|
||||
lower.result_insts_len += 1;
|
||||
break :op .{ .mem = Memory.initSib(mem_op.sib.ptr_size, .{ .base = .{
|
||||
.reg = reg.to64(),
|
||||
@ -482,7 +483,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
|
||||
}) },
|
||||
.lea => {
|
||||
emit_mnemonic = .mov;
|
||||
break :op .{ .imm = Immediate.s(0) };
|
||||
break :op .{ .imm = .s(0) };
|
||||
},
|
||||
.mov => break :op .{ .mem = Memory.initSib(mem_op.sib.ptr_size, .{
|
||||
.base = .{ .reg = .ds },
|
||||
@ -541,7 +542,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
|
||||
};
|
||||
}
|
||||
lower.result_insts[lower.result_insts_len] =
|
||||
try Instruction.new(emit_prefix, emit_mnemonic, emit_ops);
|
||||
try Instruction.new(emit_prefix, emit_mnemonic, emit_ops, lower.target);
|
||||
lower.result_insts_len += 1;
|
||||
}
|
||||
|
||||
@ -743,7 +744,7 @@ fn pushPopRegList(lower: *Lower, comptime mnemonic: Mnemonic, inst: Mir.Inst) Er
|
||||
while (it.next()) |i| {
|
||||
try lower.emit(.directive, .@".cfi_rel_offset", &.{
|
||||
.{ .reg = callee_preserved_regs[i] },
|
||||
.{ .imm = Immediate.s(off) },
|
||||
.{ .imm = .s(off) },
|
||||
});
|
||||
off += 8;
|
||||
}
|
||||
|
||||
@ -214,6 +214,10 @@ pub const Inst = struct {
|
||||
p_q,
|
||||
/// Packed ___ Double Quadword
|
||||
p_dq,
|
||||
/// ___ Aligned Packed Integer Values
|
||||
_dqa,
|
||||
/// ___ Unaligned Packed Integer Values
|
||||
_dqu,
|
||||
|
||||
/// ___ Scalar Single-Precision Values
|
||||
_ss,
|
||||
@ -234,6 +238,10 @@ pub const Inst = struct {
|
||||
v_d,
|
||||
/// VEX-Encoded ___ QuadWord
|
||||
v_q,
|
||||
/// VEX-Encoded ___ Aligned Packed Integer Values
|
||||
v_dqa,
|
||||
/// VEX-Encoded ___ Unaligned Packed Integer Values
|
||||
v_dqu,
|
||||
/// VEX-Encoded ___ Integer Data
|
||||
v_i128,
|
||||
/// VEX-Encoded Packed ___
|
||||
@ -362,6 +370,8 @@ pub const Inst = struct {
|
||||
/// Move scalar double-precision floating-point value
|
||||
/// Move doubleword
|
||||
/// Move quadword
|
||||
/// Move aligned packed integer values
|
||||
/// Move unaligned packed integer values
|
||||
mov,
|
||||
/// Move data after swapping bytes
|
||||
movbe,
|
||||
@ -609,10 +619,6 @@ pub const Inst = struct {
|
||||
cvttps2dq,
|
||||
/// Convert with truncation scalar double-precision floating-point value to doubleword integer
|
||||
cvttsd2si,
|
||||
/// Move aligned packed integer values
|
||||
movdqa,
|
||||
/// Move unaligned packed integer values
|
||||
movdqu,
|
||||
/// Packed interleave shuffle of quadruplets of single-precision floating-point values
|
||||
/// Packed interleave shuffle of pairs of double-precision floating-point values
|
||||
/// Shuffle packed doublewords
|
||||
|
||||
@ -479,8 +479,8 @@ pub const RegisterOffset = struct { reg: Register, off: i32 = 0 };
|
||||
pub const SymbolOffset = struct { sym_index: u32, off: i32 = 0 };
|
||||
|
||||
pub const Memory = struct {
|
||||
base: Base,
|
||||
mod: Mod,
|
||||
base: Base = .none,
|
||||
mod: Mod = .{ .rm = .{} },
|
||||
|
||||
pub const Base = union(enum(u2)) {
|
||||
none,
|
||||
@ -503,7 +503,7 @@ pub const Memory = struct {
|
||||
off: u64,
|
||||
|
||||
pub const Rm = struct {
|
||||
size: Size,
|
||||
size: Size = .none,
|
||||
index: Register = .none,
|
||||
scale: Scale = .@"1",
|
||||
disp: i32 = 0,
|
||||
@ -512,6 +512,7 @@ pub const Memory = struct {
|
||||
|
||||
pub const Size = enum(u4) {
|
||||
none,
|
||||
ptr,
|
||||
byte,
|
||||
word,
|
||||
dword,
|
||||
@ -548,9 +549,10 @@ pub const Memory = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn bitSize(s: Size) u64 {
|
||||
pub fn bitSize(s: Size, target: *const std.Target) u64 {
|
||||
return switch (s) {
|
||||
.none => 0,
|
||||
.ptr => target.ptrBitWidth(),
|
||||
.byte => 8,
|
||||
.word => 16,
|
||||
.dword => 32,
|
||||
@ -569,8 +571,11 @@ pub const Memory = struct {
|
||||
writer: anytype,
|
||||
) @TypeOf(writer).Error!void {
|
||||
if (s == .none) return;
|
||||
try writer.writeAll(@tagName(s));
|
||||
try writer.writeAll(" ptr");
|
||||
if (s != .ptr) {
|
||||
try writer.writeAll(@tagName(s));
|
||||
try writer.writeByte(' ');
|
||||
}
|
||||
try writer.writeAll("ptr");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -167,11 +167,11 @@ pub const Instruction = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn bitSize(mem: Memory) u64 {
|
||||
pub fn bitSize(mem: Memory, target: *const std.Target) u64 {
|
||||
return switch (mem) {
|
||||
.rip => |r| r.ptr_size.bitSize(),
|
||||
.sib => |s| s.ptr_size.bitSize(),
|
||||
.moffs => 64,
|
||||
.rip => |r| r.ptr_size.bitSize(target),
|
||||
.sib => |s| s.ptr_size.bitSize(target),
|
||||
.moffs => target.ptrBitWidth(),
|
||||
};
|
||||
}
|
||||
};
|
||||
@ -314,16 +314,21 @@ pub const Instruction = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub fn new(prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) !Instruction {
|
||||
pub fn new(
|
||||
prefix: Prefix,
|
||||
mnemonic: Mnemonic,
|
||||
ops: []const Operand,
|
||||
target: *const std.Target,
|
||||
) !Instruction {
|
||||
const encoding: Encoding = switch (prefix) {
|
||||
else => (try Encoding.findByMnemonic(prefix, mnemonic, ops)) orelse {
|
||||
else => (try Encoding.findByMnemonic(prefix, mnemonic, ops, target)) orelse {
|
||||
log.err("no encoding found for: {s} {s} {s} {s} {s} {s}", .{
|
||||
@tagName(prefix),
|
||||
@tagName(mnemonic),
|
||||
@tagName(if (ops.len > 0) Encoding.Op.fromOperand(ops[0]) else .none),
|
||||
@tagName(if (ops.len > 1) Encoding.Op.fromOperand(ops[1]) else .none),
|
||||
@tagName(if (ops.len > 2) Encoding.Op.fromOperand(ops[2]) else .none),
|
||||
@tagName(if (ops.len > 3) Encoding.Op.fromOperand(ops[3]) else .none),
|
||||
@tagName(if (ops.len > 0) Encoding.Op.fromOperand(ops[0], target) else .none),
|
||||
@tagName(if (ops.len > 1) Encoding.Op.fromOperand(ops[1], target) else .none),
|
||||
@tagName(if (ops.len > 2) Encoding.Op.fromOperand(ops[2], target) else .none),
|
||||
@tagName(if (ops.len > 3) Encoding.Op.fromOperand(ops[3], target) else .none),
|
||||
});
|
||||
return error.InvalidInstruction;
|
||||
},
|
||||
@ -332,10 +337,10 @@ pub const Instruction = struct {
|
||||
.data = .{
|
||||
.op_en = .zo,
|
||||
.ops = .{
|
||||
if (ops.len > 0) Encoding.Op.fromOperand(ops[0]) else .none,
|
||||
if (ops.len > 1) Encoding.Op.fromOperand(ops[1]) else .none,
|
||||
if (ops.len > 2) Encoding.Op.fromOperand(ops[2]) else .none,
|
||||
if (ops.len > 3) Encoding.Op.fromOperand(ops[3]) else .none,
|
||||
if (ops.len > 0) Encoding.Op.fromOperand(ops[0], target) else .none,
|
||||
if (ops.len > 1) Encoding.Op.fromOperand(ops[1], target) else .none,
|
||||
if (ops.len > 2) Encoding.Op.fromOperand(ops[2], target) else .none,
|
||||
if (ops.len > 3) Encoding.Op.fromOperand(ops[3], target) else .none,
|
||||
},
|
||||
.opc_len = 0,
|
||||
.opc = undefined,
|
||||
|
||||
@ -976,6 +976,7 @@ const x86_64 = struct {
|
||||
it: *RelocsIterator,
|
||||
) !void {
|
||||
dev.check(.x86_64_backend);
|
||||
const t = &elf_file.base.comp.root_mod.resolved_target.result;
|
||||
const is_static = elf_file.base.isStatic();
|
||||
const is_dyn_lib = elf_file.isEffectivelyDynLib();
|
||||
|
||||
@ -1046,7 +1047,7 @@ const x86_64 = struct {
|
||||
.GOTTPOFF => {
|
||||
const should_relax = blk: {
|
||||
if (is_dyn_lib or symbol.flags.import) break :blk false;
|
||||
if (!x86_64.canRelaxGotTpOff(code.?[r_offset - 3 ..])) break :blk false;
|
||||
if (!x86_64.canRelaxGotTpOff(code.?[r_offset - 3 ..], t)) break :blk false;
|
||||
break :blk true;
|
||||
};
|
||||
if (!should_relax) {
|
||||
@ -1090,6 +1091,7 @@ const x86_64 = struct {
|
||||
stream: anytype,
|
||||
) (error{ InvalidInstruction, CannotEncode } || RelocError)!void {
|
||||
dev.check(.x86_64_backend);
|
||||
const t = &elf_file.base.comp.root_mod.resolved_target.result;
|
||||
const diags = &elf_file.base.comp.link_diags;
|
||||
const r_type: elf.R_X86_64 = @enumFromInt(rel.r_type());
|
||||
const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
|
||||
@ -1120,7 +1122,7 @@ const x86_64 = struct {
|
||||
|
||||
.GOTPCRELX => {
|
||||
if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: {
|
||||
x86_64.relaxGotpcrelx(code[r_offset - 2 ..]) catch break :blk;
|
||||
x86_64.relaxGotpcrelx(code[r_offset - 2 ..], t) catch break :blk;
|
||||
try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little);
|
||||
return;
|
||||
}
|
||||
@ -1129,7 +1131,7 @@ const x86_64 = struct {
|
||||
|
||||
.REX_GOTPCRELX => {
|
||||
if (!target.flags.import and !target.isIFunc(elf_file) and !target.isAbs(elf_file)) blk: {
|
||||
x86_64.relaxRexGotpcrelx(code[r_offset - 3 ..]) catch break :blk;
|
||||
x86_64.relaxRexGotpcrelx(code[r_offset - 3 ..], t) catch break :blk;
|
||||
try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little);
|
||||
return;
|
||||
}
|
||||
@ -1184,7 +1186,7 @@ const x86_64 = struct {
|
||||
const S_ = target.tlsDescAddress(elf_file);
|
||||
try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);
|
||||
} else {
|
||||
x86_64.relaxGotPcTlsDesc(code[r_offset - 3 ..]) catch {
|
||||
x86_64.relaxGotPcTlsDesc(code[r_offset - 3 ..], t) catch {
|
||||
var err = try diags.addErrorWithNotes(1);
|
||||
try err.addMsg("could not relax {s}", .{@tagName(r_type)});
|
||||
err.addNote("in {}:{s} at offset 0x{x}", .{
|
||||
@ -1208,7 +1210,7 @@ const x86_64 = struct {
|
||||
const S_ = target.gotTpAddress(elf_file);
|
||||
try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);
|
||||
} else {
|
||||
x86_64.relaxGotTpOff(code[r_offset - 3 ..]);
|
||||
x86_64.relaxGotTpOff(code[r_offset - 3 ..], t);
|
||||
try cwriter.writeInt(i32, @as(i32, @intCast(S - TP)), .little);
|
||||
}
|
||||
},
|
||||
@ -1269,31 +1271,31 @@ const x86_64 = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn relaxGotpcrelx(code: []u8) !void {
|
||||
fn relaxGotpcrelx(code: []u8, t: *const std.Target) !void {
|
||||
dev.check(.x86_64_backend);
|
||||
const old_inst = disassemble(code) orelse return error.RelaxFailure;
|
||||
const inst = switch (old_inst.encoding.mnemonic) {
|
||||
.call => try Instruction.new(old_inst.prefix, .call, &.{
|
||||
// TODO: hack to force imm32s in the assembler
|
||||
.{ .imm = Immediate.s(-129) },
|
||||
}),
|
||||
}, t),
|
||||
.jmp => try Instruction.new(old_inst.prefix, .jmp, &.{
|
||||
// TODO: hack to force imm32s in the assembler
|
||||
.{ .imm = Immediate.s(-129) },
|
||||
}),
|
||||
}, t),
|
||||
else => return error.RelaxFailure,
|
||||
};
|
||||
relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding });
|
||||
const nop = try Instruction.new(.none, .nop, &.{});
|
||||
const nop = try Instruction.new(.none, .nop, &.{}, t);
|
||||
try encode(&.{ nop, inst }, code);
|
||||
}
|
||||
|
||||
fn relaxRexGotpcrelx(code: []u8) !void {
|
||||
fn relaxRexGotpcrelx(code: []u8, t: *const std.Target) !void {
|
||||
dev.check(.x86_64_backend);
|
||||
const old_inst = disassemble(code) orelse return error.RelaxFailure;
|
||||
switch (old_inst.encoding.mnemonic) {
|
||||
.mov => {
|
||||
const inst = try Instruction.new(old_inst.prefix, .lea, &old_inst.ops);
|
||||
const inst = try Instruction.new(old_inst.prefix, .lea, &old_inst.ops, t);
|
||||
relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding });
|
||||
try encode(&.{inst}, code);
|
||||
},
|
||||
@ -1398,7 +1400,7 @@ const x86_64 = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn canRelaxGotTpOff(code: []const u8) bool {
|
||||
fn canRelaxGotTpOff(code: []const u8, t: *const std.Target) bool {
|
||||
dev.check(.x86_64_backend);
|
||||
const old_inst = disassemble(code) orelse return false;
|
||||
switch (old_inst.encoding.mnemonic) {
|
||||
@ -1406,7 +1408,7 @@ const x86_64 = struct {
|
||||
old_inst.ops[0],
|
||||
// TODO: hack to force imm32s in the assembler
|
||||
.{ .imm = Immediate.s(-129) },
|
||||
})) |inst| {
|
||||
}, t)) |inst| {
|
||||
inst.encode(std.io.null_writer, .{}) catch return false;
|
||||
return true;
|
||||
} else |_| return false,
|
||||
@ -1414,7 +1416,7 @@ const x86_64 = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn relaxGotTpOff(code: []u8) void {
|
||||
fn relaxGotTpOff(code: []u8, t: *const std.Target) void {
|
||||
dev.check(.x86_64_backend);
|
||||
const old_inst = disassemble(code) orelse unreachable;
|
||||
switch (old_inst.encoding.mnemonic) {
|
||||
@ -1423,7 +1425,7 @@ const x86_64 = struct {
|
||||
old_inst.ops[0],
|
||||
// TODO: hack to force imm32s in the assembler
|
||||
.{ .imm = Immediate.s(-129) },
|
||||
}) catch unreachable;
|
||||
}, t) catch unreachable;
|
||||
relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding });
|
||||
encode(&.{inst}, code) catch unreachable;
|
||||
},
|
||||
@ -1431,7 +1433,7 @@ const x86_64 = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn relaxGotPcTlsDesc(code: []u8) !void {
|
||||
fn relaxGotPcTlsDesc(code: []u8, target: *const std.Target) !void {
|
||||
dev.check(.x86_64_backend);
|
||||
const old_inst = disassemble(code) orelse return error.RelaxFailure;
|
||||
switch (old_inst.encoding.mnemonic) {
|
||||
@ -1440,7 +1442,7 @@ const x86_64 = struct {
|
||||
old_inst.ops[0],
|
||||
// TODO: hack to force imm32s in the assembler
|
||||
.{ .imm = Immediate.s(-129) },
|
||||
});
|
||||
}, target);
|
||||
relocs_log.debug(" relaxing {} => {}", .{ old_inst.encoding, inst.encoding });
|
||||
try encode(&.{inst}, code);
|
||||
},
|
||||
|
||||
@ -264,11 +264,48 @@ fn testBinary(comptime op: anytype) !void {
|
||||
0xed533d18f8657f3f, 0x1ddd7cd7f6bab957,
|
||||
});
|
||||
|
||||
if (false) try testType(@Vector(1, u128), .{
|
||||
try testType(@Vector(1, u128), .{
|
||||
0x5f11e16b0ca3392f907a857881455d2e,
|
||||
}, .{
|
||||
0xf9142d73b408fd6955922f9fc147f7d7,
|
||||
});
|
||||
try testType(@Vector(2, u128), .{
|
||||
0xee0fb41fabd805923fb21b5c658e3a87,
|
||||
0x2352e74aad6c58b3255ff0bba5aa6552,
|
||||
}, .{
|
||||
0x8d822f9fdd9cb9a5b43513b14419b224,
|
||||
0x1aef2a02704379e38ead4d53d69e4cc4,
|
||||
});
|
||||
try testType(@Vector(4, u128), .{
|
||||
0xc74437a4ea3bbbb193dbf0ea2f0c5281,
|
||||
0x039e4b1640868248780db1834a0027eb,
|
||||
0xb9e8bb34155b2b238da20331d08ff85b,
|
||||
0x863802d34a54c2e6aa71dd0f067c4904,
|
||||
}, .{
|
||||
0x7471bae24ff7b84ab107f86ba2b7d1e7,
|
||||
0x8f34c449d0576e682c20bda74aa6b6c9,
|
||||
0x1f34c3efa167b61c48c9d5ec01a1a93f,
|
||||
0x71c8318fcf3ddc7be058c73a52dce9e3,
|
||||
});
|
||||
try testType(@Vector(8, u128), .{
|
||||
0xbf2db71463037f55ee338431f902a906,
|
||||
0xb7ad317626655f38ab25ae30d8a1aa67,
|
||||
0x7d3c5a3ffaa607b5560d69ae3fcf7863,
|
||||
0x009a39a8badf8b628c686dc176aa1273,
|
||||
0x49dba3744c91304cc7bbbdab61b6c969,
|
||||
0x6ec664b624f7acf79ce69d80ed7bc85c,
|
||||
0xe02d7a303c0f00c39010f3b815547f1c,
|
||||
0xb13e1ee914616f58cffe6acd33d9b5c8,
|
||||
}, .{
|
||||
0x2f2d355a071942a7384f82ba72a945b8,
|
||||
0x61f151b3afec8cb7664f813cecf581d1,
|
||||
0x5bfbf5484f3a07f0eacc4739ff48af80,
|
||||
0x59c0abbf8d829cf525a87d5c9c41a38a,
|
||||
0xdad8b18eb680f0520ca49ebfb5842e22,
|
||||
0xa05adcaedd9057480b3ba0413d003cec,
|
||||
0x8b0b4a27fc94a0e90652d19bc755b63d,
|
||||
0xa858bce5ad0e48c13588a4e170e8667c,
|
||||
});
|
||||
}
|
||||
|
||||
inline fn bitAnd(comptime Type: type, lhs: Type, rhs: Type) @TypeOf(lhs & rhs) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user