mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
aarch64: implement more assembler instructions
This commit is contained in:
parent
59de7e3a57
commit
d625158354
8 changed files with 7876 additions and 1764 deletions
|
|
@ -674,7 +674,7 @@ test lessThan {
|
||||||
try testing.expect(lessThan(u8, "", "a"));
|
try testing.expect(lessThan(u8, "", "a"));
|
||||||
}
|
}
|
||||||
|
|
||||||
const eqlBytes_allowed = switch (builtin.zig_backend) {
|
const use_vectors = switch (builtin.zig_backend) {
|
||||||
// These backends don't support vectors yet.
|
// These backends don't support vectors yet.
|
||||||
.stage2_aarch64,
|
.stage2_aarch64,
|
||||||
.stage2_powerpc,
|
.stage2_powerpc,
|
||||||
|
|
@ -682,16 +682,17 @@ const eqlBytes_allowed = switch (builtin.zig_backend) {
|
||||||
=> false,
|
=> false,
|
||||||
// The SPIR-V backend does not support the optimized path yet.
|
// The SPIR-V backend does not support the optimized path yet.
|
||||||
.stage2_spirv => false,
|
.stage2_spirv => false,
|
||||||
// The naive memory comparison implementation is more useful for fuzzers to
|
else => true,
|
||||||
// find interesting inputs.
|
|
||||||
else => !builtin.fuzz,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The naive memory comparison implementation is more useful for fuzzers to find interesting inputs.
|
||||||
|
const use_vectors_for_comparison = use_vectors and !builtin.fuzz;
|
||||||
|
|
||||||
/// Returns true if and only if the slices have the same length and all elements
|
/// Returns true if and only if the slices have the same length and all elements
|
||||||
/// compare true using equality operator.
|
/// compare true using equality operator.
|
||||||
pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
|
pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
|
||||||
if (!@inComptime() and @sizeOf(T) != 0 and std.meta.hasUniqueRepresentation(T) and
|
if (!@inComptime() and @sizeOf(T) != 0 and std.meta.hasUniqueRepresentation(T) and
|
||||||
eqlBytes_allowed)
|
use_vectors_for_comparison)
|
||||||
{
|
{
|
||||||
return eqlBytes(sliceAsBytes(a), sliceAsBytes(b));
|
return eqlBytes(sliceAsBytes(a), sliceAsBytes(b));
|
||||||
}
|
}
|
||||||
|
|
@ -726,7 +727,7 @@ test eql {
|
||||||
|
|
||||||
/// std.mem.eql heavily optimized for slices of bytes.
|
/// std.mem.eql heavily optimized for slices of bytes.
|
||||||
fn eqlBytes(a: []const u8, b: []const u8) bool {
|
fn eqlBytes(a: []const u8, b: []const u8) bool {
|
||||||
comptime assert(eqlBytes_allowed);
|
comptime assert(use_vectors_for_comparison);
|
||||||
|
|
||||||
if (a.len != b.len) return false;
|
if (a.len != b.len) return false;
|
||||||
if (a.len == 0 or a.ptr == b.ptr) return true;
|
if (a.len == 0 or a.ptr == b.ptr) return true;
|
||||||
|
|
@ -1088,15 +1089,10 @@ test len {
|
||||||
try testing.expect(len(c_ptr) == 2);
|
try testing.expect(len(c_ptr) == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
const backend_supports_vectors = switch (builtin.zig_backend) {
|
|
||||||
.stage2_llvm, .stage2_c => true,
|
|
||||||
else => false,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn indexOfSentinel(comptime T: type, comptime sentinel: T, p: [*:sentinel]const T) usize {
|
pub fn indexOfSentinel(comptime T: type, comptime sentinel: T, p: [*:sentinel]const T) usize {
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
|
|
||||||
if (backend_supports_vectors and
|
if (use_vectors_for_comparison and
|
||||||
!std.debug.inValgrind() and // https://github.com/ziglang/zig/issues/17717
|
!std.debug.inValgrind() and // https://github.com/ziglang/zig/issues/17717
|
||||||
!@inComptime() and
|
!@inComptime() and
|
||||||
(@typeInfo(T) == .int or @typeInfo(T) == .float) and std.math.isPowerOfTwo(@bitSizeOf(T)))
|
(@typeInfo(T) == .int or @typeInfo(T) == .float) and std.math.isPowerOfTwo(@bitSizeOf(T)))
|
||||||
|
|
@ -1263,7 +1259,7 @@ pub fn indexOfScalarPos(comptime T: type, slice: []const T, start_index: usize,
|
||||||
if (start_index >= slice.len) return null;
|
if (start_index >= slice.len) return null;
|
||||||
|
|
||||||
var i: usize = start_index;
|
var i: usize = start_index;
|
||||||
if (backend_supports_vectors and
|
if (use_vectors_for_comparison and
|
||||||
!std.debug.inValgrind() and // https://github.com/ziglang/zig/issues/17717
|
!std.debug.inValgrind() and // https://github.com/ziglang/zig/issues/17717
|
||||||
!@inComptime() and
|
!@inComptime() and
|
||||||
(@typeInfo(T) == .int or @typeInfo(T) == .float) and std.math.isPowerOfTwo(@bitSizeOf(T)))
|
(@typeInfo(T) == .int or @typeInfo(T) == .float) and std.math.isPowerOfTwo(@bitSizeOf(T)))
|
||||||
|
|
@ -3609,7 +3605,7 @@ inline fn reverseVector(comptime N: usize, comptime T: type, a: []T) [N]T {
|
||||||
pub fn reverse(comptime T: type, items: []T) void {
|
pub fn reverse(comptime T: type, items: []T) void {
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
const end = items.len / 2;
|
const end = items.len / 2;
|
||||||
if (backend_supports_vectors and
|
if (use_vectors and
|
||||||
!@inComptime() and
|
!@inComptime() and
|
||||||
@bitSizeOf(T) > 0 and
|
@bitSizeOf(T) > 0 and
|
||||||
std.math.isPowerOfTwo(@bitSizeOf(T)))
|
std.math.isPowerOfTwo(@bitSizeOf(T)))
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -3,9 +3,18 @@ mnemonic_operands_separator: []const u8 = " ",
|
||||||
operands_separator: []const u8 = ", ",
|
operands_separator: []const u8 = ", ",
|
||||||
enable_aliases: bool = true,
|
enable_aliases: bool = true,
|
||||||
|
|
||||||
pub const Case = enum { lower, upper };
|
pub const Case = enum {
|
||||||
|
lower,
|
||||||
|
upper,
|
||||||
|
pub fn convert(case: Case, c: u8) u8 {
|
||||||
|
return switch (case) {
|
||||||
|
.lower => std.ascii.toLower(c),
|
||||||
|
.upper => std.ascii.toUpper(c),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Writer) std.Io.Writer.Error!void {
|
pub fn printInstruction(dis: Disassemble, inst: aarch64.encoding.Instruction, writer: *std.Io.Writer) std.Io.Writer.Error!void {
|
||||||
unallocated: switch (inst.decode()) {
|
unallocated: switch (inst.decode()) {
|
||||||
.unallocated => break :unallocated,
|
.unallocated => break :unallocated,
|
||||||
.reserved => |reserved| switch (reserved.decode()) {
|
.reserved => |reserved| switch (reserved.decode()) {
|
||||||
|
|
@ -23,13 +32,13 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
.pc_relative_addressing => |pc_relative_addressing| {
|
.pc_relative_addressing => |pc_relative_addressing| {
|
||||||
const group = pc_relative_addressing.group;
|
const group = pc_relative_addressing.group;
|
||||||
const imm = (@as(i33, group.immhi) << 2 | @as(i33, group.immlo) << 0) + @as(i33, switch (group.op) {
|
const imm = (@as(i33, group.immhi) << 2 | @as(i33, group.immlo) << 0) + @as(i33, switch (group.op) {
|
||||||
.adr => Instruction.size,
|
.adr => aarch64.encoding.Instruction.size,
|
||||||
.adrp => 0,
|
.adrp => 0,
|
||||||
});
|
});
|
||||||
return writer.print("{f}{s}{f}{s}.{c}0x{x}", .{
|
return writer.print("{f}{s}{f}{s}.{c}0x{x}", .{
|
||||||
fmtCase(group.op, dis.case),
|
fmtCase(group.op, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rd.decodeInteger(.doubleword, .{}).fmtCase(dis.case),
|
group.Rd.decode(.{}).x().fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
@as(u8, if (imm < 0) '-' else '+'),
|
@as(u8, if (imm < 0) '-' else '+'),
|
||||||
switch (group.op) {
|
switch (group.op) {
|
||||||
|
|
@ -45,8 +54,8 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
const sf = group.sf;
|
const sf = group.sf;
|
||||||
const sh = group.sh;
|
const sh = group.sh;
|
||||||
const imm12 = group.imm12;
|
const imm12 = group.imm12;
|
||||||
const Rn = group.Rn.decodeInteger(sf, .{ .sp = true });
|
const Rn = group.Rn.decode(.{ .sp = true }).general(sf);
|
||||||
const Rd = group.Rd.decodeInteger(sf, .{ .sp = !S });
|
const Rd = group.Rd.decode(.{ .sp = !S }).general(sf);
|
||||||
const elide_shift = sh == .@"0";
|
const elide_shift = sh == .@"0";
|
||||||
if (dis.enable_aliases and op == .add and S == false and elide_shift and imm12 == 0 and
|
if (dis.enable_aliases and op == .add and S == false and elide_shift and imm12 == 0 and
|
||||||
(Rn.alias == .sp or Rd.alias == .sp)) try writer.print("{f}{s}{f}{s}{f}", .{
|
(Rn.alias == .sp or Rd.alias == .sp)) try writer.print("{f}{s}{f}{s}{f}", .{
|
||||||
|
|
@ -82,8 +91,8 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
.word => @as(i32, @bitCast(@as(u32, @intCast(decoded_imm)))),
|
.word => @as(i32, @bitCast(@as(u32, @intCast(decoded_imm)))),
|
||||||
.doubleword => @as(i64, @bitCast(decoded_imm)),
|
.doubleword => @as(i64, @bitCast(decoded_imm)),
|
||||||
};
|
};
|
||||||
const Rn = group.Rn.decodeInteger(sf, .{});
|
const Rn = group.Rn.decode(.{}).general(sf);
|
||||||
const Rd = group.Rd.decodeInteger(sf, .{ .sp = decoded != .ands });
|
const Rd = group.Rd.decode(.{ .sp = decoded != .ands }).general(sf);
|
||||||
return if (dis.enable_aliases and decoded == .orr and Rn.alias == .zr and !group.imm.moveWidePreferred(sf)) writer.print("{f}{s}{f}{s}#{s}0x{x}", .{
|
return if (dis.enable_aliases and decoded == .orr and Rn.alias == .zr and !group.imm.moveWidePreferred(sf)) writer.print("{f}{s}{f}{s}#{s}0x{x}", .{
|
||||||
fmtCase(.mov, dis.case),
|
fmtCase(.mov, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
|
|
@ -115,7 +124,7 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
const sf = group.sf;
|
const sf = group.sf;
|
||||||
const hw = group.hw;
|
const hw = group.hw;
|
||||||
const imm16 = group.imm16;
|
const imm16 = group.imm16;
|
||||||
const Rd = group.Rd.decodeInteger(sf, .{});
|
const Rd = group.Rd.decode(.{}).general(sf);
|
||||||
const elide_shift = hw == .@"0";
|
const elide_shift = hw == .@"0";
|
||||||
if (dis.enable_aliases and switch (decoded) {
|
if (dis.enable_aliases and switch (decoded) {
|
||||||
.unallocated => unreachable,
|
.unallocated => unreachable,
|
||||||
|
|
@ -166,9 +175,9 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
return writer.print("{f}{s}{f}{s}{f}{s}#{d}{s}#{d}", .{
|
return writer.print("{f}{s}{f}{s}{f}{s}#{d}{s}#{d}", .{
|
||||||
fmtCase(decoded, dis.case),
|
fmtCase(decoded, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rd.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rd.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rn.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rn.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.imm.immr,
|
group.imm.immr,
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
|
|
@ -183,11 +192,11 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
return writer.print("{f}{s}{f}{s}{f}{s}{f}{s}#{d}", .{
|
return writer.print("{f}{s}{f}{s}{f}{s}{f}{s}#{d}", .{
|
||||||
fmtCase(decoded, dis.case),
|
fmtCase(decoded, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rd.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rd.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rn.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rn.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rm.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rm.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.imms,
|
group.imms,
|
||||||
});
|
});
|
||||||
|
|
@ -248,7 +257,7 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
const decoded = unconditional_branch_register.decode();
|
const decoded = unconditional_branch_register.decode();
|
||||||
if (decoded == .unallocated) break :unallocated;
|
if (decoded == .unallocated) break :unallocated;
|
||||||
const group = unconditional_branch_register.group;
|
const group = unconditional_branch_register.group;
|
||||||
const Rn = group.Rn.decodeInteger(.doubleword, .{});
|
const Rn = group.Rn.decode(.{}).x();
|
||||||
try writer.print("{f}", .{fmtCase(decoded, dis.case)});
|
try writer.print("{f}", .{fmtCase(decoded, dis.case)});
|
||||||
return if (decoded != .ret or Rn.alias != .r30) try writer.print("{s}{f}", .{
|
return if (decoded != .ret or Rn.alias != .r30) try writer.print("{s}{f}", .{
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
|
|
@ -271,7 +280,7 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
return writer.print("{f}{s}{f}{s}.{c}0x{x}", .{
|
return writer.print("{f}{s}{f}{s}.{c}0x{x}", .{
|
||||||
fmtCase(group.op, dis.case),
|
fmtCase(group.op, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rt.decodeInteger(group.sf, .{}).fmtCase(dis.case),
|
group.Rt.decode(.{}).general(group.sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
@as(u8, if (imm < 0) '-' else '+'),
|
@as(u8, if (imm < 0) '-' else '+'),
|
||||||
@abs(imm) << 2,
|
@abs(imm) << 2,
|
||||||
|
|
@ -283,7 +292,7 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
return writer.print("{f}{s}{f}{s}#0x{d}{s}.{c}0x{x}", .{
|
return writer.print("{f}{s}{f}{s}#0x{d}{s}.{c}0x{x}", .{
|
||||||
fmtCase(group.op, dis.case),
|
fmtCase(group.op, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rt.decodeInteger(@enumFromInt(group.b5), .{}).fmtCase(dis.case),
|
group.Rt.decode(.{}).general(@enumFromInt(group.b5)).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
@as(u6, group.b5) << 5 |
|
@as(u6, group.b5) << 5 |
|
||||||
@as(u6, group.b40) << 0,
|
@as(u6, group.b40) << 0,
|
||||||
|
|
@ -303,15 +312,15 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
const decoded = integer.decode();
|
const decoded = integer.decode();
|
||||||
if (decoded == .unallocated) break :unallocated;
|
if (decoded == .unallocated) break :unallocated;
|
||||||
const group = integer.group;
|
const group = integer.group;
|
||||||
const sf: aarch64.encoding.Register.IntegerSize = @enumFromInt(group.opc >> 1);
|
const sf: aarch64.encoding.Register.GeneralSize = @enumFromInt(group.opc >> 1);
|
||||||
return writer.print("{f}{s}{f}{s}{f}{s}[{f}]{s}#{s}0x{x}", .{
|
return writer.print("{f}{s}{f}{s}{f}{s}[{f}]{s}#{s}0x{x}", .{
|
||||||
fmtCase(decoded, dis.case),
|
fmtCase(decoded, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rt.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rt.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rt2.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rt2.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
|
group.Rn.decode(.{ .sp = true }).x().fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
if (group.imm7 < 0) "-" else "",
|
if (group.imm7 < 0) "-" else "",
|
||||||
@as(u10, @abs(group.imm7)) << (@as(u2, 2) + @intFromEnum(sf)),
|
@as(u10, @abs(group.imm7)) << (@as(u2, 2) + @intFromEnum(sf)),
|
||||||
|
|
@ -325,11 +334,11 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
return writer.print("{f}{s}{f}{s}{f}{s}[{f}]{s}#{s}0x{x}", .{
|
return writer.print("{f}{s}{f}{s}{f}{s}[{f}]{s}#{s}0x{x}", .{
|
||||||
fmtCase(decoded, dis.case),
|
fmtCase(decoded, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rt.decodeVector(vs).fmtCase(dis.case),
|
group.Rt.decode(.{ .V = true }).scalar(vs).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rt2.decodeVector(vs).fmtCase(dis.case),
|
group.Rt2.decode(.{ .V = true }).scalar(vs).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
|
group.Rn.decode(.{ .sp = true }).x().fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
if (group.imm7 < 0) "-" else "",
|
if (group.imm7 < 0) "-" else "",
|
||||||
@as(u11, @abs(group.imm7)) << (@as(u3, 2) + @intFromEnum(vs)),
|
@as(u11, @abs(group.imm7)) << (@as(u3, 2) + @intFromEnum(vs)),
|
||||||
|
|
@ -341,15 +350,15 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
const decoded = integer.decode();
|
const decoded = integer.decode();
|
||||||
if (decoded == .unallocated) break :unallocated;
|
if (decoded == .unallocated) break :unallocated;
|
||||||
const group = integer.group;
|
const group = integer.group;
|
||||||
const sf: aarch64.encoding.Register.IntegerSize = @enumFromInt(group.opc >> 1);
|
const sf: aarch64.encoding.Register.GeneralSize = @enumFromInt(group.opc >> 1);
|
||||||
try writer.print("{f}{s}{f}{s}{f}{s}[{f}", .{
|
try writer.print("{f}{s}{f}{s}{f}{s}[{f}", .{
|
||||||
fmtCase(decoded, dis.case),
|
fmtCase(decoded, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rt.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rt.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rt2.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rt2.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
|
group.Rn.decode(.{ .sp = true }).x().fmtCase(dis.case),
|
||||||
});
|
});
|
||||||
if (group.imm7 != 0) try writer.print("{s}#{s}0x{x}", .{
|
if (group.imm7 != 0) try writer.print("{s}#{s}0x{x}", .{
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
|
|
@ -366,11 +375,11 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
try writer.print("{f}{s}{f}{s}{f}{s}[{f}", .{
|
try writer.print("{f}{s}{f}{s}{f}{s}[{f}", .{
|
||||||
fmtCase(decoded, dis.case),
|
fmtCase(decoded, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rt.decodeVector(vs).fmtCase(dis.case),
|
group.Rt.decode(.{ .V = true }).scalar(vs).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rt2.decodeVector(vs).fmtCase(dis.case),
|
group.Rt2.decode(.{ .V = true }).scalar(vs).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
|
group.Rn.decode(.{ .sp = true }).x().fmtCase(dis.case),
|
||||||
});
|
});
|
||||||
if (group.imm7 != 0) try writer.print("{s}#{s}0x{x}", .{
|
if (group.imm7 != 0) try writer.print("{s}#{s}0x{x}", .{
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
|
|
@ -385,15 +394,15 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
const decoded = integer.decode();
|
const decoded = integer.decode();
|
||||||
if (decoded == .unallocated) break :unallocated;
|
if (decoded == .unallocated) break :unallocated;
|
||||||
const group = integer.group;
|
const group = integer.group;
|
||||||
const sf: aarch64.encoding.Register.IntegerSize = @enumFromInt(group.opc >> 1);
|
const sf: aarch64.encoding.Register.GeneralSize = @enumFromInt(group.opc >> 1);
|
||||||
return writer.print("{f}{s}{f}{s}{f}{s}[{f}{s}#{s}0x{x}]!", .{
|
return writer.print("{f}{s}{f}{s}{f}{s}[{f}{s}#{s}0x{x}]!", .{
|
||||||
fmtCase(decoded, dis.case),
|
fmtCase(decoded, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rt.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rt.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rt2.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rt2.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
|
group.Rn.decode(.{ .sp = true }).x().fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
if (group.imm7 < 0) "-" else "",
|
if (group.imm7 < 0) "-" else "",
|
||||||
@as(u10, @abs(group.imm7)) << (@as(u2, 2) + @intFromEnum(sf)),
|
@as(u10, @abs(group.imm7)) << (@as(u2, 2) + @intFromEnum(sf)),
|
||||||
|
|
@ -407,11 +416,11 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
return writer.print("{f}{s}{f}{s}{f}{s}[{f}{s}#{s}0x{x}]!", .{
|
return writer.print("{f}{s}{f}{s}{f}{s}[{f}{s}#{s}0x{x}]!", .{
|
||||||
fmtCase(decoded, dis.case),
|
fmtCase(decoded, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rt.decodeVector(vs).fmtCase(dis.case),
|
group.Rt.decode(.{ .V = true }).scalar(vs).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rt2.decodeVector(vs).fmtCase(dis.case),
|
group.Rt2.decode(.{ .V = true }).scalar(vs).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
|
group.Rn.decode(.{ .sp = true }).x().fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
if (group.imm7 < 0) "-" else "",
|
if (group.imm7 < 0) "-" else "",
|
||||||
@as(u11, @abs(group.imm7)) << (@as(u3, 2) + @intFromEnum(vs)),
|
@as(u11, @abs(group.imm7)) << (@as(u3, 2) + @intFromEnum(vs)),
|
||||||
|
|
@ -422,7 +431,7 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
.register_immediate_post_indexed => |register_immediate_post_indexed| switch (register_immediate_post_indexed.decode()) {
|
.register_immediate_post_indexed => |register_immediate_post_indexed| switch (register_immediate_post_indexed.decode()) {
|
||||||
.integer => |integer| {
|
.integer => |integer| {
|
||||||
const decoded = integer.decode();
|
const decoded = integer.decode();
|
||||||
const sf: aarch64.encoding.Register.IntegerSize = switch (decoded) {
|
const sf: aarch64.encoding.Register.GeneralSize = switch (decoded) {
|
||||||
.unallocated => break :unallocated,
|
.unallocated => break :unallocated,
|
||||||
.strb, .ldrb, .strh, .ldrh => .word,
|
.strb, .ldrb, .strh, .ldrh => .word,
|
||||||
inline .ldrsb, .ldrsh => |encoded| switch (encoded.opc0) {
|
inline .ldrsb, .ldrsh => |encoded| switch (encoded.opc0) {
|
||||||
|
|
@ -436,9 +445,9 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
return writer.print("{f}{s}{f}{s}[{f}]{s}#{s}0x{x}", .{
|
return writer.print("{f}{s}{f}{s}[{f}]{s}#{s}0x{x}", .{
|
||||||
fmtCase(decoded, dis.case),
|
fmtCase(decoded, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rt.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rt.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
|
group.Rn.decode(.{ .sp = true }).x().fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
if (group.imm9 < 0) "-" else "",
|
if (group.imm9 < 0) "-" else "",
|
||||||
@abs(group.imm9),
|
@abs(group.imm9),
|
||||||
|
|
@ -450,7 +459,7 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
.register_immediate_pre_indexed => |register_immediate_pre_indexed| switch (register_immediate_pre_indexed.decode()) {
|
.register_immediate_pre_indexed => |register_immediate_pre_indexed| switch (register_immediate_pre_indexed.decode()) {
|
||||||
.integer => |integer| {
|
.integer => |integer| {
|
||||||
const decoded = integer.decode();
|
const decoded = integer.decode();
|
||||||
const sf: aarch64.encoding.Register.IntegerSize = switch (decoded) {
|
const sf: aarch64.encoding.Register.GeneralSize = switch (decoded) {
|
||||||
.unallocated => break :unallocated,
|
.unallocated => break :unallocated,
|
||||||
inline .ldrsb, .ldrsh => |encoded| switch (encoded.opc0) {
|
inline .ldrsb, .ldrsh => |encoded| switch (encoded.opc0) {
|
||||||
0b0 => .doubleword,
|
0b0 => .doubleword,
|
||||||
|
|
@ -464,9 +473,9 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
return writer.print("{f}{s}{f}{s}[{f}{s}#{s}0x{x}]!", .{
|
return writer.print("{f}{s}{f}{s}[{f}{s}#{s}0x{x}]!", .{
|
||||||
fmtCase(decoded, dis.case),
|
fmtCase(decoded, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rt.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rt.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
|
group.Rn.decode(.{ .sp = true }).x().fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
if (group.imm9 < 0) "-" else "",
|
if (group.imm9 < 0) "-" else "",
|
||||||
@abs(group.imm9),
|
@abs(group.imm9),
|
||||||
|
|
@ -479,9 +488,9 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
return writer.print("{f}{s}{f}{s}[{f}{s}#{s}0x{x}]!", .{
|
return writer.print("{f}{s}{f}{s}[{f}{s}#{s}0x{x}]!", .{
|
||||||
fmtCase(decoded, dis.case),
|
fmtCase(decoded, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rt.decodeVector(group.opc1.decode(group.size)).fmtCase(dis.case),
|
group.Rt.decode(.{ .V = true }).scalar(group.opc1.decode(group.size)).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
|
group.Rn.decode(.{ .sp = true }).x().fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
if (group.imm9 < 0) "-" else "",
|
if (group.imm9 < 0) "-" else "",
|
||||||
@abs(group.imm9),
|
@abs(group.imm9),
|
||||||
|
|
@ -491,7 +500,7 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
.register_register_offset => |register_register_offset| switch (register_register_offset.decode()) {
|
.register_register_offset => |register_register_offset| switch (register_register_offset.decode()) {
|
||||||
.integer => |integer| {
|
.integer => |integer| {
|
||||||
const decoded = integer.decode();
|
const decoded = integer.decode();
|
||||||
const sf: aarch64.encoding.Register.IntegerSize = switch (decoded) {
|
const sf: aarch64.encoding.Register.GeneralSize = switch (decoded) {
|
||||||
.unallocated, .prfm => break :unallocated,
|
.unallocated, .prfm => break :unallocated,
|
||||||
.strb, .ldrb, .strh, .ldrh => .word,
|
.strb, .ldrb, .strh, .ldrh => .word,
|
||||||
inline .ldrsb, .ldrsh => |encoded| switch (encoded.opc0) {
|
inline .ldrsb, .ldrsh => |encoded| switch (encoded.opc0) {
|
||||||
|
|
@ -505,11 +514,11 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
try writer.print("{f}{s}{f}{s}[{f}{s}{f}", .{
|
try writer.print("{f}{s}{f}{s}[{f}{s}{f}", .{
|
||||||
fmtCase(decoded, dis.case),
|
fmtCase(decoded, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rt.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rt.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
|
group.Rn.decode(.{ .sp = true }).x().fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rm.decodeInteger(group.option.sf(), .{}).fmtCase(dis.case),
|
group.Rm.decode(.{}).general(group.option.sf()).fmtCase(dis.case),
|
||||||
});
|
});
|
||||||
if (group.option != .lsl or group.S) {
|
if (group.option != .lsl or group.S) {
|
||||||
try writer.print("{s}{f}", .{
|
try writer.print("{s}{f}", .{
|
||||||
|
|
@ -527,7 +536,7 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
.register_unsigned_immediate => |register_unsigned_immediate| switch (register_unsigned_immediate.decode()) {
|
.register_unsigned_immediate => |register_unsigned_immediate| switch (register_unsigned_immediate.decode()) {
|
||||||
.integer => |integer| {
|
.integer => |integer| {
|
||||||
const decoded = integer.decode();
|
const decoded = integer.decode();
|
||||||
const sf: aarch64.encoding.Register.IntegerSize = switch (decoded) {
|
const sf: aarch64.encoding.Register.GeneralSize = switch (decoded) {
|
||||||
.unallocated, .prfm => break :unallocated,
|
.unallocated, .prfm => break :unallocated,
|
||||||
.strb, .ldrb, .strh, .ldrh => .word,
|
.strb, .ldrb, .strh, .ldrh => .word,
|
||||||
inline .ldrsb, .ldrsh => |encoded| switch (encoded.opc0) {
|
inline .ldrsb, .ldrsh => |encoded| switch (encoded.opc0) {
|
||||||
|
|
@ -541,9 +550,9 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
try writer.print("{f}{s}{f}{s}[{f}", .{
|
try writer.print("{f}{s}{f}{s}[{f}", .{
|
||||||
fmtCase(decoded, dis.case),
|
fmtCase(decoded, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rt.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rt.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rn.decodeInteger(.doubleword, .{ .sp = true }).fmtCase(dis.case),
|
group.Rn.decode(.{ .sp = true }).x().fmtCase(dis.case),
|
||||||
});
|
});
|
||||||
if (group.imm12 > 0) try writer.print("{s}#0x{x}", .{
|
if (group.imm12 > 0) try writer.print("{s}#0x{x}", .{
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
|
|
@ -562,13 +571,21 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
const group = data_processing_two_source.group;
|
const group = data_processing_two_source.group;
|
||||||
const sf = group.sf;
|
const sf = group.sf;
|
||||||
return writer.print("{f}{s}{f}{s}{f}{s}{f}", .{
|
return writer.print("{f}{s}{f}{s}{f}{s}{f}", .{
|
||||||
fmtCase(decoded, dis.case),
|
if (dis.enable_aliases) fmtCase(@as(enum { udiv, sdiv, lsl, lsr, asr, ror }, switch (decoded) {
|
||||||
|
.unallocated => unreachable,
|
||||||
|
.udiv => .udiv,
|
||||||
|
.sdiv => .sdiv,
|
||||||
|
.lslv => .lsl,
|
||||||
|
.lsrv => .lsr,
|
||||||
|
.asrv => .asr,
|
||||||
|
.rorv => .ror,
|
||||||
|
}), dis.case) else fmtCase(decoded, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rd.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rd.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rn.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rn.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rm.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rm.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.data_processing_one_source => |data_processing_one_source| {
|
.data_processing_one_source => |data_processing_one_source| {
|
||||||
|
|
@ -579,9 +596,9 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
return writer.print("{f}{s}{f}{s}{f}", .{
|
return writer.print("{f}{s}{f}{s}{f}", .{
|
||||||
fmtCase(decoded, dis.case),
|
fmtCase(decoded, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rd.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rd.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rn.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rn.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
.logical_shifted_register => |logical_shifted_register| {
|
.logical_shifted_register => |logical_shifted_register| {
|
||||||
|
|
@ -590,10 +607,10 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
const group = logical_shifted_register.group;
|
const group = logical_shifted_register.group;
|
||||||
const sf = group.sf;
|
const sf = group.sf;
|
||||||
const shift = group.shift;
|
const shift = group.shift;
|
||||||
const Rm = group.Rm.decodeInteger(sf, .{});
|
const Rm = group.Rm.decode(.{}).general(sf);
|
||||||
const amount = group.imm6;
|
const amount = group.imm6;
|
||||||
const Rn = group.Rn.decodeInteger(sf, .{});
|
const Rn = group.Rn.decode(.{}).general(sf);
|
||||||
const Rd = group.Rd.decodeInteger(sf, .{});
|
const Rd = group.Rd.decode(.{}).general(sf);
|
||||||
const elide_shift = shift == .lsl and amount == 0;
|
const elide_shift = shift == .lsl and amount == 0;
|
||||||
if (dis.enable_aliases and switch (decoded) {
|
if (dis.enable_aliases and switch (decoded) {
|
||||||
else => false,
|
else => false,
|
||||||
|
|
@ -636,10 +653,10 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
const group = add_subtract_shifted_register.group;
|
const group = add_subtract_shifted_register.group;
|
||||||
const sf = group.sf;
|
const sf = group.sf;
|
||||||
const shift = group.shift;
|
const shift = group.shift;
|
||||||
const Rm = group.Rm.decodeInteger(sf, .{});
|
const Rm = group.Rm.decode(.{}).general(sf);
|
||||||
const imm6 = group.imm6;
|
const imm6 = group.imm6;
|
||||||
const Rn = group.Rn.decodeInteger(sf, .{});
|
const Rn = group.Rn.decode(.{}).general(sf);
|
||||||
const Rd = group.Rd.decodeInteger(sf, .{});
|
const Rd = group.Rd.decode(.{}).general(sf);
|
||||||
if (dis.enable_aliases and group.S and Rd.alias == .zr) try writer.print("{f}{s}{f}{s}{f}", .{
|
if (dis.enable_aliases and group.S and Rd.alias == .zr) try writer.print("{f}{s}{f}{s}{f}", .{
|
||||||
fmtCase(@as(enum { cmn, cmp }, switch (group.op) {
|
fmtCase(@as(enum { cmn, cmp }, switch (group.op) {
|
||||||
.add => .cmn,
|
.add => .cmn,
|
||||||
|
|
@ -678,9 +695,9 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
if (decoded == .unallocated) break :unallocated;
|
if (decoded == .unallocated) break :unallocated;
|
||||||
const group = add_subtract_extended_register.group;
|
const group = add_subtract_extended_register.group;
|
||||||
const sf = group.sf;
|
const sf = group.sf;
|
||||||
const Rm = group.Rm.decodeInteger(group.option.sf(), .{});
|
const Rm = group.Rm.decode(.{}).general(group.option.sf());
|
||||||
const Rn = group.Rn.decodeInteger(sf, .{ .sp = true });
|
const Rn = group.Rn.decode(.{ .sp = true }).general(sf);
|
||||||
const Rd = group.Rd.decodeInteger(sf, .{ .sp = true });
|
const Rd = group.Rd.decode(.{ .sp = true }).general(sf);
|
||||||
if (dis.enable_aliases and group.S and Rd.alias == .zr) try writer.print("{f}{s}{f}{s}{f}", .{
|
if (dis.enable_aliases and group.S and Rd.alias == .zr) try writer.print("{f}{s}{f}{s}{f}", .{
|
||||||
fmtCase(@as(enum { cmn, cmp }, switch (group.op) {
|
fmtCase(@as(enum { cmn, cmp }, switch (group.op) {
|
||||||
.add => .cmn,
|
.add => .cmn,
|
||||||
|
|
@ -699,7 +716,7 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
Rm.fmtCase(dis.case),
|
Rm.fmtCase(dis.case),
|
||||||
});
|
});
|
||||||
return if (group.option != @as(Instruction.DataProcessingRegister.AddSubtractExtendedRegister.Option, switch (sf) {
|
return if (group.option != @as(aarch64.encoding.Instruction.DataProcessingRegister.AddSubtractExtendedRegister.Option, switch (sf) {
|
||||||
.word => .uxtw,
|
.word => .uxtw,
|
||||||
.doubleword => .uxtx,
|
.doubleword => .uxtx,
|
||||||
}) or group.imm3 != 0) writer.print("{s}{f} #{d}", .{
|
}) or group.imm3 != 0) writer.print("{s}{f} #{d}", .{
|
||||||
|
|
@ -712,9 +729,9 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
const decoded = add_subtract_with_carry.decode();
|
const decoded = add_subtract_with_carry.decode();
|
||||||
const group = add_subtract_with_carry.group;
|
const group = add_subtract_with_carry.group;
|
||||||
const sf = group.sf;
|
const sf = group.sf;
|
||||||
const Rm = group.Rm.decodeInteger(sf, .{});
|
const Rm = group.Rm.decode(.{}).general(sf);
|
||||||
const Rn = group.Rn.decodeInteger(sf, .{});
|
const Rn = group.Rn.decode(.{}).general(sf);
|
||||||
const Rd = group.Rd.decodeInteger(sf, .{});
|
const Rd = group.Rd.decode(.{}).general(sf);
|
||||||
return if (dis.enable_aliases and group.op == .sbc and Rn.alias == .zr) try writer.print("{f}{s}{f}{s}{f}", .{
|
return if (dis.enable_aliases and group.op == .sbc and Rn.alias == .zr) try writer.print("{f}{s}{f}{s}{f}", .{
|
||||||
fmtCase(@as(enum { ngc, ngcs }, switch (group.S) {
|
fmtCase(@as(enum { ngc, ngcs }, switch (group.S) {
|
||||||
false => .ngc,
|
false => .ngc,
|
||||||
|
|
@ -743,10 +760,10 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
if (decoded == .unallocated) break :unallocated;
|
if (decoded == .unallocated) break :unallocated;
|
||||||
const group = conditional_select.group;
|
const group = conditional_select.group;
|
||||||
const sf = group.sf;
|
const sf = group.sf;
|
||||||
const Rm = group.Rm.decodeInteger(sf, .{});
|
const Rm = group.Rm.decode(.{}).general(sf);
|
||||||
const cond = group.cond;
|
const cond = group.cond;
|
||||||
const Rn = group.Rn.decodeInteger(sf, .{});
|
const Rn = group.Rn.decode(.{}).general(sf);
|
||||||
const Rd = group.Rd.decodeInteger(sf, .{});
|
const Rd = group.Rd.decode(.{}).general(sf);
|
||||||
return if (dis.enable_aliases and group.op != group.op2 and Rm.alias == .zr and cond != .al and cond != .nv and Rn.alias == Rm.alias) writer.print("{f}{s}{f}{s}{f}", .{
|
return if (dis.enable_aliases and group.op != group.op2 and Rm.alias == .zr and cond != .al and cond != .nv and Rn.alias == Rm.alias) writer.print("{f}{s}{f}{s}{f}", .{
|
||||||
fmtCase(@as(enum { cset, csetm }, switch (decoded) {
|
fmtCase(@as(enum { cset, csetm }, switch (decoded) {
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
|
|
@ -784,34 +801,447 @@ pub fn printInstruction(dis: Disassemble, inst: Instruction, writer: *std.Io.Wri
|
||||||
},
|
},
|
||||||
.data_processing_three_source => |data_processing_three_source| {
|
.data_processing_three_source => |data_processing_three_source| {
|
||||||
const decoded = data_processing_three_source.decode();
|
const decoded = data_processing_three_source.decode();
|
||||||
if (decoded == .unallocated) break :unallocated;
|
|
||||||
const group = data_processing_three_source.group;
|
const group = data_processing_three_source.group;
|
||||||
const sf = group.sf;
|
const sf = group.sf;
|
||||||
|
const operand_sf = switch (decoded) {
|
||||||
|
.unallocated => break :unallocated,
|
||||||
|
.madd, .msub, .smulh, .umulh => sf,
|
||||||
|
.smaddl, .smsubl, .umaddl, .umsubl => .word,
|
||||||
|
};
|
||||||
|
const Ra = group.Ra.decode(.{}).general(sf);
|
||||||
|
const elide_addend = dis.enable_aliases and Ra.alias == .zr;
|
||||||
try writer.print("{f}{s}{f}{s}{f}{s}{f}", .{
|
try writer.print("{f}{s}{f}{s}{f}{s}{f}", .{
|
||||||
fmtCase(decoded, dis.case),
|
if (elide_addend) fmtCase(@as(enum {
|
||||||
|
mul,
|
||||||
|
mneg,
|
||||||
|
smull,
|
||||||
|
smnegl,
|
||||||
|
smulh,
|
||||||
|
umull,
|
||||||
|
umnegl,
|
||||||
|
umulh,
|
||||||
|
}, switch (decoded) {
|
||||||
|
.unallocated => unreachable,
|
||||||
|
.madd => .mul,
|
||||||
|
.msub => .mneg,
|
||||||
|
.smaddl => .smull,
|
||||||
|
.smsubl => .smnegl,
|
||||||
|
.smulh => .smulh,
|
||||||
|
.umaddl => .umull,
|
||||||
|
.umsubl => .umnegl,
|
||||||
|
.umulh => .umulh,
|
||||||
|
}), dis.case) else fmtCase(decoded, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
group.Rd.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rd.decode(.{}).general(sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rn.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rn.decode(.{}).general(operand_sf).fmtCase(dis.case),
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Rm.decodeInteger(sf, .{}).fmtCase(dis.case),
|
group.Rm.decode(.{}).general(operand_sf).fmtCase(dis.case),
|
||||||
});
|
});
|
||||||
return switch (decoded) {
|
return if (!elide_addend) switch (decoded) {
|
||||||
.unallocated => unreachable,
|
.unallocated => unreachable,
|
||||||
.madd, .msub, .smaddl, .smsubl, .umaddl, .umsubl => writer.print("{s}{f}", .{
|
.madd, .msub, .smaddl, .smsubl, .umaddl, .umsubl => writer.print("{s}{f}", .{
|
||||||
dis.operands_separator,
|
dis.operands_separator,
|
||||||
group.Ra.decodeInteger(sf, .{}).fmtCase(dis.case),
|
Ra.fmtCase(dis.case),
|
||||||
}),
|
}),
|
||||||
.smulh, .umulh => {},
|
.smulh, .umulh => {},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.data_processing_vector => {},
|
.data_processing_vector => |data_processing_vector| switch (data_processing_vector.decode()) {
|
||||||
|
.unallocated => break :unallocated,
|
||||||
|
.simd_scalar_copy => |simd_scalar_copy| {
|
||||||
|
const decoded = simd_scalar_copy.decode();
|
||||||
|
if (decoded == .unallocated) break :unallocated;
|
||||||
|
const group = simd_scalar_copy.group;
|
||||||
|
const elem_size = @ctz(group.imm5);
|
||||||
|
return writer.print("{f}{s}{f}{s}{f}", .{
|
||||||
|
if (dis.enable_aliases and decoded == .dup)
|
||||||
|
fmtCase(.mov, dis.case)
|
||||||
|
else
|
||||||
|
fmtCase(decoded, dis.case),
|
||||||
|
dis.mnemonic_operands_separator,
|
||||||
|
group.Rd.decode(.{ .V = true }).scalar(@enumFromInt(elem_size)).fmtCase(dis.case),
|
||||||
|
dis.operands_separator,
|
||||||
|
group.Rn.decode(.{ .V = true }).element(
|
||||||
|
@enumFromInt(elem_size),
|
||||||
|
@intCast(group.imm5 >> (elem_size + 1)),
|
||||||
|
).fmtCase(dis.case),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
.simd_scalar_two_register_miscellaneous_fp16 => |simd_scalar_two_register_miscellaneous_fp16| {
|
||||||
|
const decoded = simd_scalar_two_register_miscellaneous_fp16.decode();
|
||||||
|
if (decoded == .unallocated) break :unallocated;
|
||||||
|
const group = simd_scalar_two_register_miscellaneous_fp16.group;
|
||||||
|
try writer.print("{f}{s}{f}{s}{f}", .{
|
||||||
|
fmtCase(decoded, dis.case),
|
||||||
|
dis.mnemonic_operands_separator,
|
||||||
|
group.Rd.decode(.{ .V = true }).h().fmtCase(dis.case),
|
||||||
|
dis.operands_separator,
|
||||||
|
group.Rn.decode(.{ .V = true }).h().fmtCase(dis.case),
|
||||||
|
});
|
||||||
|
return switch (decoded) {
|
||||||
|
.unallocated => unreachable,
|
||||||
|
else => {},
|
||||||
|
.fcmgt,
|
||||||
|
.fcmeq,
|
||||||
|
.fcmlt,
|
||||||
|
.fcmge,
|
||||||
|
.fcmle,
|
||||||
|
=> writer.print("{s}#0.0", .{dis.operands_separator}),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
.simd_scalar_two_register_miscellaneous => |simd_scalar_two_register_miscellaneous| {
|
||||||
|
const decoded = simd_scalar_two_register_miscellaneous.decode();
|
||||||
|
const group = simd_scalar_two_register_miscellaneous.group;
|
||||||
|
const elem_size = switch (decoded) {
|
||||||
|
.unallocated => break :unallocated,
|
||||||
|
inline .fcvtns,
|
||||||
|
.fcvtms,
|
||||||
|
.fcvtas,
|
||||||
|
.scvtf,
|
||||||
|
.fcvtps,
|
||||||
|
.fcvtzs,
|
||||||
|
.fcvtxn,
|
||||||
|
.fcvtnu,
|
||||||
|
.fcvtmu,
|
||||||
|
.fcvtau,
|
||||||
|
.ucvtf,
|
||||||
|
.fcvtpu,
|
||||||
|
.fcvtzu,
|
||||||
|
=> |f| f.sz.toScalarSize(),
|
||||||
|
else => group.size.toScalarSize(),
|
||||||
|
};
|
||||||
|
try writer.print("{f}{s}{f}{s}{f}", .{
|
||||||
|
fmtCase(decoded, dis.case),
|
||||||
|
dis.mnemonic_operands_separator,
|
||||||
|
group.Rd.decode(.{ .V = true }).scalar(elem_size).fmtCase(dis.case),
|
||||||
|
dis.operands_separator,
|
||||||
|
group.Rn.decode(.{ .V = true }).scalar(switch (decoded) {
|
||||||
|
.unallocated => unreachable,
|
||||||
|
else => elem_size,
|
||||||
|
.sqxtn => elem_size.w(),
|
||||||
|
}).fmtCase(dis.case),
|
||||||
|
});
|
||||||
|
return switch (decoded) {
|
||||||
|
.unallocated => unreachable,
|
||||||
|
else => {},
|
||||||
|
.cmgt,
|
||||||
|
.cmeq,
|
||||||
|
.cmlt,
|
||||||
|
.cmge,
|
||||||
|
.cmle,
|
||||||
|
=> writer.print("{s}#0", .{dis.operands_separator}),
|
||||||
|
.fcmgt,
|
||||||
|
.fcmeq,
|
||||||
|
.fcmlt,
|
||||||
|
.fcmge,
|
||||||
|
.fcmle,
|
||||||
|
=> writer.print("{s}#0.0", .{dis.operands_separator}),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
.simd_scalar_pairwise => {},
|
||||||
|
.simd_copy => |simd_copy| {
|
||||||
|
const decoded = simd_copy.decode();
|
||||||
|
if (decoded == .unallocated) break :unallocated;
|
||||||
|
const group = simd_copy.group;
|
||||||
|
const elem_size = @ctz(group.imm5);
|
||||||
|
return writer.print("{f}{s}{f}{s}{f}", .{
|
||||||
|
if (dis.enable_aliases and switch (decoded) {
|
||||||
|
.unallocated => unreachable,
|
||||||
|
.dup, .smov => false,
|
||||||
|
.umov => elem_size >= 2,
|
||||||
|
.ins => true,
|
||||||
|
}) fmtCase(.mov, dis.case) else fmtCase(decoded, dis.case),
|
||||||
|
dis.mnemonic_operands_separator,
|
||||||
|
switch (decoded) {
|
||||||
|
.unallocated => unreachable,
|
||||||
|
.dup => |dup| group.Rd.decode(.{ .V = true }).vector(.wrap(.{
|
||||||
|
.size = dup.Q,
|
||||||
|
.elem_size = @enumFromInt(elem_size),
|
||||||
|
})),
|
||||||
|
inline .smov, .umov => |mov| group.Rd.decode(.{}).general(mov.Q),
|
||||||
|
.ins => group.Rd.decode(.{ .V = true }).element(
|
||||||
|
@enumFromInt(elem_size),
|
||||||
|
@intCast(group.imm5 >> (elem_size + 1)),
|
||||||
|
),
|
||||||
|
}.fmtCase(dis.case),
|
||||||
|
dis.operands_separator,
|
||||||
|
switch (decoded) {
|
||||||
|
.unallocated => unreachable,
|
||||||
|
.dup => |dup| switch (dup.imm4) {
|
||||||
|
.element => group.Rn.decode(.{ .V = true }).element(
|
||||||
|
@enumFromInt(elem_size),
|
||||||
|
@intCast(group.imm5 >> (elem_size + 1)),
|
||||||
|
),
|
||||||
|
.general => group.Rn.decode(.{}).general(switch (elem_size) {
|
||||||
|
0...2 => .word,
|
||||||
|
3 => .doubleword,
|
||||||
|
else => unreachable,
|
||||||
|
}),
|
||||||
|
_ => unreachable,
|
||||||
|
},
|
||||||
|
.smov, .umov => group.Rn.decode(.{ .V = true }).element(
|
||||||
|
@enumFromInt(elem_size),
|
||||||
|
@intCast(group.imm5 >> (elem_size + 1)),
|
||||||
|
),
|
||||||
|
.ins => |ins| switch (ins.op) {
|
||||||
|
.element => group.Rn.decode(.{ .V = true }).element(
|
||||||
|
@enumFromInt(elem_size),
|
||||||
|
@intCast(group.imm4 >> @intCast(elem_size)),
|
||||||
|
),
|
||||||
|
.general => group.Rn.decode(.{}).general(switch (elem_size) {
|
||||||
|
0...2 => .word,
|
||||||
|
3 => .doubleword,
|
||||||
|
else => unreachable,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}.fmtCase(dis.case),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
.simd_two_register_miscellaneous_fp16 => |simd_two_register_miscellaneous_fp16| {
|
||||||
|
const decoded = simd_two_register_miscellaneous_fp16.decode();
|
||||||
|
if (decoded == .unallocated) break :unallocated;
|
||||||
|
const group = simd_two_register_miscellaneous_fp16.group;
|
||||||
|
const arrangement: aarch64.encoding.Register.Arrangement = .wrap(.{
|
||||||
|
.size = group.Q,
|
||||||
|
.elem_size = .half,
|
||||||
|
});
|
||||||
|
try writer.print("{f}{s}{f}{s}{f}", .{
|
||||||
|
fmtCase(decoded, dis.case),
|
||||||
|
dis.mnemonic_operands_separator,
|
||||||
|
group.Rd.decode(.{ .V = true }).vector(arrangement).fmtCase(dis.case),
|
||||||
|
dis.operands_separator,
|
||||||
|
group.Rn.decode(.{ .V = true }).vector(arrangement).fmtCase(dis.case),
|
||||||
|
});
|
||||||
|
return switch (decoded) {
|
||||||
|
.unallocated => unreachable,
|
||||||
|
else => {},
|
||||||
|
.fcmgt,
|
||||||
|
.fcmeq,
|
||||||
|
.fcmlt,
|
||||||
|
.fcmge,
|
||||||
|
.fcmle,
|
||||||
|
=> writer.print("{s}#0.0", .{dis.operands_separator}),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
.simd_two_register_miscellaneous => |simd_two_register_miscellaneous| {
|
||||||
|
const decoded = simd_two_register_miscellaneous.decode();
|
||||||
|
const group = simd_two_register_miscellaneous.group;
|
||||||
|
const elem_size = switch (decoded) {
|
||||||
|
.unallocated => break :unallocated,
|
||||||
|
inline .frintn,
|
||||||
|
.frintm,
|
||||||
|
.fcvtns,
|
||||||
|
.fcvtms,
|
||||||
|
.fcvtas,
|
||||||
|
.scvtf,
|
||||||
|
.frintp,
|
||||||
|
.frintz,
|
||||||
|
.fcvtps,
|
||||||
|
.fcvtzs,
|
||||||
|
.fcvtxn,
|
||||||
|
.frinta,
|
||||||
|
.frintx,
|
||||||
|
.fcvtnu,
|
||||||
|
.fcvtmu,
|
||||||
|
.fcvtau,
|
||||||
|
.ucvtf,
|
||||||
|
.frinti,
|
||||||
|
.fcvtpu,
|
||||||
|
.fcvtzu,
|
||||||
|
=> |f| f.sz.toSize(),
|
||||||
|
else => group.size,
|
||||||
|
};
|
||||||
|
const arrangement: aarch64.encoding.Register.Arrangement = .wrap(.{
|
||||||
|
.size = group.Q,
|
||||||
|
.elem_size = elem_size,
|
||||||
|
});
|
||||||
|
try writer.print("{f}{s}{s}{f}{s}{f}", .{
|
||||||
|
fmtCase(decoded, dis.case),
|
||||||
|
switch (decoded) {
|
||||||
|
.unallocated => unreachable,
|
||||||
|
else => "",
|
||||||
|
.sqxtn => switch (group.Q) {
|
||||||
|
.double => "",
|
||||||
|
.quad => "2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dis.mnemonic_operands_separator,
|
||||||
|
group.Rd.decode(.{ .V = true }).vector(arrangement).fmtCase(dis.case),
|
||||||
|
dis.operands_separator,
|
||||||
|
group.Rn.decode(.{ .V = true }).vector(switch (decoded) {
|
||||||
|
.unallocated => unreachable,
|
||||||
|
else => arrangement,
|
||||||
|
.sqxtn => .wrap(.{
|
||||||
|
.size = .quad,
|
||||||
|
.elem_size = elem_size.w(),
|
||||||
|
}),
|
||||||
|
}).fmtCase(dis.case),
|
||||||
|
});
|
||||||
|
return switch (decoded) {
|
||||||
|
.unallocated => unreachable,
|
||||||
|
else => {},
|
||||||
|
.cmgt,
|
||||||
|
.cmeq,
|
||||||
|
.cmlt,
|
||||||
|
.cmge,
|
||||||
|
.cmle,
|
||||||
|
=> writer.print("{s}#0", .{dis.operands_separator}),
|
||||||
|
.fcmgt,
|
||||||
|
.fcmeq,
|
||||||
|
.fcmlt,
|
||||||
|
.fcmge,
|
||||||
|
.fcmle,
|
||||||
|
=> writer.print("{s}#0.0", .{dis.operands_separator}),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
.simd_across_lanes => |simd_across_lanes| {
|
||||||
|
const decoded = simd_across_lanes.decode();
|
||||||
|
if (decoded == .unallocated) break :unallocated;
|
||||||
|
const group = simd_across_lanes.group;
|
||||||
|
const arrangement: aarch64.encoding.Register.Arrangement = .wrap(.{
|
||||||
|
.size = group.Q,
|
||||||
|
.elem_size = group.size,
|
||||||
|
});
|
||||||
|
return writer.print("{f}{s}{f}{s}{f}", .{
|
||||||
|
fmtCase(decoded, dis.case),
|
||||||
|
dis.mnemonic_operands_separator,
|
||||||
|
group.Rd.decode(.{ .V = true }).scalar(group.size.toScalarSize()).fmtCase(dis.case),
|
||||||
|
dis.operands_separator,
|
||||||
|
group.Rn.decode(.{ .V = true }).vector(arrangement).fmtCase(dis.case),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
.simd_three_same => |simd_three_same| {
|
||||||
|
const decoded = simd_three_same.decode();
|
||||||
|
if (decoded == .unallocated) break :unallocated;
|
||||||
|
const group = simd_three_same.group;
|
||||||
|
const arrangement: aarch64.encoding.Register.Arrangement = .wrap(.{
|
||||||
|
.size = group.Q,
|
||||||
|
.elem_size = switch (decoded) {
|
||||||
|
.unallocated => break :unallocated,
|
||||||
|
.addp => group.size,
|
||||||
|
.@"and", .bic, .orr, .orn, .eor, .bsl, .bit, .bif => .byte,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const Rd = group.Rd.decode(.{ .V = true }).vector(arrangement);
|
||||||
|
const Rn = group.Rn.decode(.{ .V = true }).vector(arrangement);
|
||||||
|
const Rm = group.Rm.decode(.{ .V = true }).vector(arrangement);
|
||||||
|
return if (dis.enable_aliases and decoded == .orr and Rm.alias == Rn.alias) try writer.print("{f}{s}{f}{s}{f}", .{
|
||||||
|
fmtCase(.mov, dis.case),
|
||||||
|
dis.mnemonic_operands_separator,
|
||||||
|
Rd.fmtCase(dis.case),
|
||||||
|
dis.operands_separator,
|
||||||
|
Rn.fmtCase(dis.case),
|
||||||
|
}) else try writer.print("{f}{s}{f}{s}{f}{s}{f}", .{
|
||||||
|
fmtCase(decoded, dis.case),
|
||||||
|
dis.mnemonic_operands_separator,
|
||||||
|
Rd.fmtCase(dis.case),
|
||||||
|
dis.operands_separator,
|
||||||
|
Rn.fmtCase(dis.case),
|
||||||
|
dis.operands_separator,
|
||||||
|
Rm.fmtCase(dis.case),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
.simd_modified_immediate => |simd_modified_immediate| {
|
||||||
|
const decoded = simd_modified_immediate.decode();
|
||||||
|
if (decoded == .unallocated) break :unallocated;
|
||||||
|
const group = simd_modified_immediate.group;
|
||||||
|
const DataProcessingVector = aarch64.encoding.Instruction.DataProcessingVector;
|
||||||
|
try writer.print("{f}{s}{f}", .{
|
||||||
|
fmtCase(decoded, dis.case),
|
||||||
|
dis.mnemonic_operands_separator,
|
||||||
|
group.Rd.decode(.{ .V = true }).vector(.wrap(.{
|
||||||
|
.size = group.Q,
|
||||||
|
.elem_size = switch (group.o2) {
|
||||||
|
0b1 => .half,
|
||||||
|
0b0 => DataProcessingVector.Sz.toSize(@enumFromInt(group.op)),
|
||||||
|
},
|
||||||
|
})).fmtCase(dis.case),
|
||||||
|
});
|
||||||
|
return switch (decoded) {
|
||||||
|
.unallocated => unreachable,
|
||||||
|
.fmov => {
|
||||||
|
const imm = DataProcessingVector.FloatImmediate.Fmov.Imm8.fromModified(.{
|
||||||
|
.imm5 = group.imm5,
|
||||||
|
.imm3 = group.imm3,
|
||||||
|
}).decode();
|
||||||
|
try writer.print("{s}#{d}{s}", .{
|
||||||
|
dis.operands_separator,
|
||||||
|
@as(f32, imm),
|
||||||
|
if (imm == @trunc(imm)) ".0" else "",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
.convert_float_fixed => {},
|
||||||
|
.convert_float_integer => |convert_float_integer| {
|
||||||
|
const decoded = convert_float_integer.decode();
|
||||||
|
if (decoded == .unallocated) break :unallocated;
|
||||||
|
const group = convert_float_integer.group;
|
||||||
|
const direction: enum { float_to_integer, integer_to_float } = switch (group.opcode) {
|
||||||
|
0b000, 0b001, 0b100, 0b101, 0b110 => .float_to_integer,
|
||||||
|
0b010, 0b011, 0b111 => .integer_to_float,
|
||||||
|
};
|
||||||
|
return writer.print("{f}{s}{f}{s}{f}", .{
|
||||||
|
fmtCase(decoded, dis.case),
|
||||||
|
dis.mnemonic_operands_separator,
|
||||||
|
@as(aarch64.encoding.Register, switch (direction) {
|
||||||
|
.float_to_integer => group.Rd.decode(.{}).general(group.sf),
|
||||||
|
.integer_to_float => switch (group.ptype) {
|
||||||
|
.single, .double, .half => group.Rd.decode(.{ .V = true }).scalar(group.ptype.toScalarSize()),
|
||||||
|
.quad => group.Rd.decode(.{ .V = true }).@"d[]"(@intCast(group.rmode)),
|
||||||
|
},
|
||||||
|
}).fmtCase(dis.case),
|
||||||
|
dis.operands_separator,
|
||||||
|
@as(aarch64.encoding.Register, switch (direction) {
|
||||||
|
.float_to_integer => switch (group.ptype) {
|
||||||
|
.single, .double, .half => group.Rn.decode(.{ .V = true }).scalar(group.ptype.toScalarSize()),
|
||||||
|
.quad => group.Rn.decode(.{ .V = true }).@"d[]"(@intCast(group.rmode)),
|
||||||
|
},
|
||||||
|
.integer_to_float => group.Rn.decode(.{}).general(group.sf),
|
||||||
|
}).fmtCase(dis.case),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
.float_data_processing_one_source => |float_data_processing_one_source| {
|
||||||
|
const decoded = float_data_processing_one_source.decode();
|
||||||
|
if (decoded == .unallocated) break :unallocated;
|
||||||
|
const group = float_data_processing_one_source.group;
|
||||||
|
return writer.print("{f}{s}{f}{s}{f}", .{
|
||||||
|
fmtCase(decoded, dis.case),
|
||||||
|
dis.mnemonic_operands_separator,
|
||||||
|
group.Rd.decode(.{ .V = true }).scalar(group.ptype.toScalarSize()).fmtCase(dis.case),
|
||||||
|
dis.operands_separator,
|
||||||
|
group.Rn.decode(.{ .V = true }).scalar(group.ptype.toScalarSize()).fmtCase(dis.case),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
.float_compare => {},
|
||||||
|
.float_immediate => |float_immediate| {
|
||||||
|
const decoded = float_immediate.decode();
|
||||||
|
const group = float_immediate.group;
|
||||||
|
const imm = switch (decoded) {
|
||||||
|
.unallocated => break :unallocated,
|
||||||
|
.fmov => |fmov| fmov.imm8.decode(),
|
||||||
|
};
|
||||||
|
return writer.print("{f}{s}{f}{s}#{d}{s}", .{
|
||||||
|
fmtCase(decoded, dis.case),
|
||||||
|
dis.mnemonic_operands_separator,
|
||||||
|
group.Rd.decode(.{ .V = true }).scalar(group.ptype.toScalarSize()).fmtCase(dis.case),
|
||||||
|
dis.operands_separator,
|
||||||
|
@as(f32, imm),
|
||||||
|
if (imm == @trunc(imm)) ".0" else "",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
.float_conditional_compare => {},
|
||||||
|
.float_data_processing_two_source => {},
|
||||||
|
.float_conditional_select => {},
|
||||||
|
.float_data_processing_three_source => {},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
return writer.print(".{f}{s}0x{x:0>8}", .{
|
return writer.print(".{f}{s}0x{x:0>8}", .{
|
||||||
fmtCase(.word, dis.case),
|
fmtCase(.word, dis.case),
|
||||||
dis.mnemonic_operands_separator,
|
dis.mnemonic_operands_separator,
|
||||||
@as(Instruction.Backing, @bitCast(inst)),
|
@as(aarch64.encoding.Instruction.Backing, @bitCast(inst)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -819,10 +1249,7 @@ fn fmtCase(tag: anytype, case: Case) struct {
|
||||||
tag: []const u8,
|
tag: []const u8,
|
||||||
case: Case,
|
case: Case,
|
||||||
pub fn format(data: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void {
|
pub fn format(data: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void {
|
||||||
for (data.tag) |c| try writer.writeByte(switch (data.case) {
|
for (data.tag) |c| try writer.writeByte(data.case.convert(c));
|
||||||
.lower => std.ascii.toLower(c),
|
|
||||||
.upper => std.ascii.toUpper(c),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} {
|
} {
|
||||||
return .{ .tag = @tagName(tag), .case = case };
|
return .{ .tag = @tagName(tag), .case = case };
|
||||||
|
|
@ -834,7 +1261,8 @@ pub const RegisterFormatter = struct {
|
||||||
pub fn format(data: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void {
|
pub fn format(data: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void {
|
||||||
switch (data.reg.format) {
|
switch (data.reg.format) {
|
||||||
.alias => try writer.print("{f}", .{fmtCase(data.reg.alias, data.case)}),
|
.alias => try writer.print("{f}", .{fmtCase(data.reg.alias, data.case)}),
|
||||||
.integer => |size| switch (data.reg.alias) {
|
.general => |size| switch (data.reg.alias) {
|
||||||
|
else => unreachable,
|
||||||
.r0,
|
.r0,
|
||||||
.r1,
|
.r1,
|
||||||
.r2,
|
.r2,
|
||||||
|
|
@ -867,23 +1295,23 @@ pub const RegisterFormatter = struct {
|
||||||
.r29,
|
.r29,
|
||||||
.r30,
|
.r30,
|
||||||
=> |alias| try writer.print("{c}{d}", .{
|
=> |alias| try writer.print("{c}{d}", .{
|
||||||
size.prefix(),
|
data.case.convert(size.prefix()),
|
||||||
@intFromEnum(alias.encode(.{})),
|
@intFromEnum(alias.encode(.{})),
|
||||||
}),
|
}),
|
||||||
.zr => try writer.print("{c}{f}", .{
|
.zr => try writer.print("{c}{f}", .{
|
||||||
size.prefix(),
|
data.case.convert(size.prefix()),
|
||||||
fmtCase(data.reg.alias, data.case),
|
fmtCase(data.reg.alias, data.case),
|
||||||
}),
|
}),
|
||||||
else => try writer.print("{s}{f}", .{
|
.sp => try writer.print("{s}{f}", .{
|
||||||
switch (size) {
|
switch (size) {
|
||||||
.word => "w",
|
.word => &.{data.case.convert('w')},
|
||||||
.doubleword => "",
|
.doubleword => "",
|
||||||
},
|
},
|
||||||
fmtCase(data.reg.alias, data.case),
|
fmtCase(data.reg.alias, data.case),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
.scalar => |size| try writer.print("{c}{d}", .{
|
.scalar => |size| try writer.print("{c}{d}", .{
|
||||||
size.prefix(),
|
data.case.convert(size.prefix()),
|
||||||
@intFromEnum(data.reg.alias.encode(.{ .V = true })),
|
@intFromEnum(data.reg.alias.encode(.{ .V = true })),
|
||||||
}),
|
}),
|
||||||
.vector => |arrangement| try writer.print("{f}.{f}", .{
|
.vector => |arrangement| try writer.print("{f}.{f}", .{
|
||||||
|
|
@ -892,14 +1320,17 @@ pub const RegisterFormatter = struct {
|
||||||
}),
|
}),
|
||||||
.element => |element| try writer.print("{f}.{c}[{d}]", .{
|
.element => |element| try writer.print("{f}.{c}[{d}]", .{
|
||||||
fmtCase(data.reg.alias, data.case),
|
fmtCase(data.reg.alias, data.case),
|
||||||
element.size.prefix(),
|
data.case.convert(element.size.prefix()),
|
||||||
element.index,
|
element.index,
|
||||||
}),
|
}),
|
||||||
|
.scalable => try writer.print("{c}{d}", .{
|
||||||
|
data.case.convert('z'),
|
||||||
|
@intFromEnum(data.reg.alias.encode(.{ .V = true })),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const aarch64 = @import("../aarch64.zig");
|
const aarch64 = @import("../aarch64.zig");
|
||||||
const Disassemble = @This();
|
const Disassemble = @This();
|
||||||
const Instruction = aarch64.encoding.Instruction;
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
|
||||||
|
|
@ -307,7 +307,6 @@ fn emitReloc(
|
||||||
.single => .LDST32_ABS_LO12_NC,
|
.single => .LDST32_ABS_LO12_NC,
|
||||||
.double => .LDST64_ABS_LO12_NC,
|
.double => .LDST64_ABS_LO12_NC,
|
||||||
.quad => .LDST128_ABS_LO12_NC,
|
.quad => .LDST128_ABS_LO12_NC,
|
||||||
.scalable, .predicate => unreachable,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
try atom.addReloc(gpa, .{
|
try atom.addReloc(gpa, .{
|
||||||
|
|
|
||||||
|
|
@ -8186,7 +8186,7 @@ fn fail(isel: *Select, comptime format: []const u8, args: anytype) error{ OutOfM
|
||||||
|
|
||||||
/// dst = src
|
/// dst = src
|
||||||
fn movImmediate(isel: *Select, dst_reg: Register, src_imm: u64) !void {
|
fn movImmediate(isel: *Select, dst_reg: Register, src_imm: u64) !void {
|
||||||
const sf = dst_reg.format.integer;
|
const sf = dst_reg.format.general;
|
||||||
if (src_imm == 0) {
|
if (src_imm == 0) {
|
||||||
const zr: Register = switch (sf) {
|
const zr: Register = switch (sf) {
|
||||||
.word => .wzr,
|
.word => .wzr,
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -829,21 +829,21 @@ fn resolveRelocInner(
|
||||||
const rd, const rn = switch (aarch64.encoding.Instruction.read(inst_code).decode()) {
|
const rd, const rn = switch (aarch64.encoding.Instruction.read(inst_code).decode()) {
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
.data_processing_immediate => |decoded| .{
|
.data_processing_immediate => |decoded| .{
|
||||||
decoded.add_subtract_immediate.group.Rd.decodeInteger(.doubleword, .{ .sp = true }),
|
decoded.add_subtract_immediate.group.Rd.decode(.{ .sp = true }),
|
||||||
decoded.add_subtract_immediate.group.Rn.decodeInteger(.doubleword, .{ .sp = true }),
|
decoded.add_subtract_immediate.group.Rn.decode(.{ .sp = true }),
|
||||||
},
|
},
|
||||||
.load_store => |decoded| .{
|
.load_store => |decoded| .{
|
||||||
decoded.register_unsigned_immediate.integer.group.Rt.decodeInteger(.doubleword, .{}),
|
decoded.register_unsigned_immediate.integer.group.Rt.decode(.{}),
|
||||||
decoded.register_unsigned_immediate.group.Rn.decodeInteger(.doubleword, .{ .sp = true }),
|
decoded.register_unsigned_immediate.group.Rn.decode(.{ .sp = true }),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
try writer.writeInt(u32, @bitCast(@as(
|
try writer.writeInt(u32, @bitCast(@as(
|
||||||
aarch64.encoding.Instruction,
|
aarch64.encoding.Instruction,
|
||||||
if (sym.getSectionFlags().tlv_ptr) .ldr(rd, .{ .unsigned_offset = .{
|
if (sym.getSectionFlags().tlv_ptr) .ldr(rd.x(), .{ .unsigned_offset = .{
|
||||||
.base = rn,
|
.base = rn.x(),
|
||||||
.offset = try divExact(self, rel, @truncate(target), 8, macho_file) * 8,
|
.offset = try divExact(self, rel, @truncate(target), 8, macho_file) * 8,
|
||||||
} }) else .add(rd, rn, .{ .immediate = @truncate(target) }),
|
} }) else .add(rd.x(), rn.x(), .{ .immediate = @truncate(target) }),
|
||||||
)), .little);
|
)), .little);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue