mirror of
https://github.com/ziglang/zig.git
synced 2024-11-27 07:32:44 +00:00
zld: use aarch64 for opcodes
This commit is contained in:
parent
dc34ac2b9e
commit
d484b3b3cb
@ -221,7 +221,8 @@ pub const Instruction = union(enum) {
|
||||
offset: u12,
|
||||
opc: u2,
|
||||
op1: u2,
|
||||
fixed: u4 = 0b111_0,
|
||||
v: u1,
|
||||
fixed: u3 = 0b111,
|
||||
size: u2,
|
||||
},
|
||||
LoadStorePairOfRegisters: packed struct {
|
||||
@ -505,6 +506,7 @@ pub const Instruction = union(enum) {
|
||||
.offset = offset.toU12(),
|
||||
.opc = opc,
|
||||
.op1 = op1,
|
||||
.v = 0,
|
||||
.size = 0b10,
|
||||
},
|
||||
};
|
||||
@ -517,6 +519,7 @@ pub const Instruction = union(enum) {
|
||||
.offset = offset.toU12(),
|
||||
.opc = opc,
|
||||
.op1 = op1,
|
||||
.v = 0,
|
||||
.size = 0b11,
|
||||
},
|
||||
};
|
||||
|
@ -10,6 +10,7 @@ const fs = std.fs;
|
||||
const macho = std.macho;
|
||||
const math = std.math;
|
||||
const log = std.log.scoped(.zld);
|
||||
const aarch64 = @import("../../codegen/aarch64.zig");
|
||||
|
||||
const Allocator = mem.Allocator;
|
||||
const CodeSignature = @import("CodeSignature.zig");
|
||||
@ -19,7 +20,6 @@ const Trie = @import("Trie.zig");
|
||||
|
||||
usingnamespace @import("commands.zig");
|
||||
usingnamespace @import("bind.zig");
|
||||
usingnamespace @import("reloc.zig");
|
||||
|
||||
allocator: *Allocator,
|
||||
|
||||
@ -968,27 +968,27 @@ fn writeStubHelperCommon(self: *Zld) !void {
|
||||
data_blk: {
|
||||
const displacement = math.cast(i21, target_addr - this_addr) catch |_| break :data_blk;
|
||||
// adr x17, disp
|
||||
mem.writeIntLittle(u32, code[0..4], Arm64.adr(17, @bitCast(u21, displacement)).toU32());
|
||||
mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.adr(.x17, displacement).toU32());
|
||||
// nop
|
||||
mem.writeIntLittle(u32, code[4..8], Arm64.nop().toU32());
|
||||
mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.nop().toU32());
|
||||
break :data_blk_outer;
|
||||
}
|
||||
data_blk: {
|
||||
const new_this_addr = this_addr + @sizeOf(u32);
|
||||
const displacement = math.cast(i21, target_addr - new_this_addr) catch |_| break :data_blk;
|
||||
// nop
|
||||
mem.writeIntLittle(u32, code[0..4], Arm64.nop().toU32());
|
||||
mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.nop().toU32());
|
||||
// adr x17, disp
|
||||
mem.writeIntLittle(u32, code[4..8], Arm64.adr(17, @bitCast(u21, displacement)).toU32());
|
||||
mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.adr(.x17, displacement).toU32());
|
||||
break :data_blk_outer;
|
||||
}
|
||||
// Jump is too big, replace adr with adrp and add.
|
||||
const this_page = @intCast(i32, this_addr >> 12);
|
||||
const target_page = @intCast(i32, target_addr >> 12);
|
||||
const pages = @bitCast(u21, @intCast(i21, target_page - this_page));
|
||||
mem.writeIntLittle(u32, code[0..4], Arm64.adrp(17, pages).toU32());
|
||||
const pages = @intCast(i21, target_page - this_page);
|
||||
mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.adrp(.x17, pages).toU32());
|
||||
const narrowed = @truncate(u12, target_addr);
|
||||
mem.writeIntLittle(u32, code[4..8], Arm64.add(17, 17, narrowed, 1).toU32());
|
||||
mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.add(.x17, .x17, narrowed, false).toU32());
|
||||
}
|
||||
// stp x16, x17, [sp, #-16]!
|
||||
code[8] = 0xf0;
|
||||
@ -1003,9 +1003,11 @@ fn writeStubHelperCommon(self: *Zld) !void {
|
||||
const displacement = math.divExact(u64, target_addr - this_addr, 4) catch |_| break :binder_blk;
|
||||
const literal = math.cast(u18, displacement) catch |_| break :binder_blk;
|
||||
// ldr x16, label
|
||||
mem.writeIntLittle(u32, code[12..16], Arm64.ldr(16, literal, 1).toU32());
|
||||
mem.writeIntLittle(u32, code[12..16], aarch64.Instruction.ldr(.x16, .{
|
||||
.literal = literal,
|
||||
}).toU32());
|
||||
// nop
|
||||
mem.writeIntLittle(u32, code[16..20], Arm64.nop().toU32());
|
||||
mem.writeIntLittle(u32, code[16..20], aarch64.Instruction.nop().toU32());
|
||||
break :binder_blk_outer;
|
||||
}
|
||||
binder_blk: {
|
||||
@ -1015,19 +1017,26 @@ fn writeStubHelperCommon(self: *Zld) !void {
|
||||
log.debug("2: disp=0x{x}, literal=0x{x}", .{ displacement, literal });
|
||||
// Pad with nop to please division.
|
||||
// nop
|
||||
mem.writeIntLittle(u32, code[12..16], Arm64.nop().toU32());
|
||||
mem.writeIntLittle(u32, code[12..16], aarch64.Instruction.nop().toU32());
|
||||
// ldr x16, label
|
||||
mem.writeIntLittle(u32, code[16..20], Arm64.ldr(16, literal, 1).toU32());
|
||||
mem.writeIntLittle(u32, code[16..20], aarch64.Instruction.ldr(.x16, .{
|
||||
.literal = literal,
|
||||
}).toU32());
|
||||
break :binder_blk_outer;
|
||||
}
|
||||
// Use adrp followed by ldr(immediate).
|
||||
const this_page = @intCast(i32, this_addr >> 12);
|
||||
const target_page = @intCast(i32, target_addr >> 12);
|
||||
const pages = @bitCast(u21, @intCast(i21, target_page - this_page));
|
||||
mem.writeIntLittle(u32, code[12..16], Arm64.adrp(16, pages).toU32());
|
||||
const pages = @intCast(i21, target_page - this_page);
|
||||
mem.writeIntLittle(u32, code[12..16], aarch64.Instruction.adrp(.x16, pages).toU32());
|
||||
const narrowed = @truncate(u12, target_addr);
|
||||
const offset = try math.divExact(u12, narrowed, 8);
|
||||
mem.writeIntLittle(u32, code[16..20], Arm64.ldrq(16, 16, offset).toU32());
|
||||
mem.writeIntLittle(u32, code[16..20], aarch64.Instruction.ldr(.x16, .{
|
||||
.register = .{
|
||||
.rn = .x16,
|
||||
.offset = aarch64.Instruction.LoadStoreOffset.imm(offset),
|
||||
},
|
||||
}).toU32());
|
||||
}
|
||||
// br x16
|
||||
code[20] = 0x00;
|
||||
@ -1099,9 +1108,11 @@ fn writeStub(self: *Zld, index: u32) !void {
|
||||
const displacement = math.divExact(u64, target_addr - this_addr, 4) catch |_| break :inner;
|
||||
const literal = math.cast(u18, displacement) catch |_| break :inner;
|
||||
// ldr x16, literal
|
||||
mem.writeIntLittle(u32, code[0..4], Arm64.ldr(16, literal, 1).toU32());
|
||||
mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.ldr(.x16, .{
|
||||
.literal = literal,
|
||||
}).toU32());
|
||||
// nop
|
||||
mem.writeIntLittle(u32, code[4..8], Arm64.nop().toU32());
|
||||
mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.nop().toU32());
|
||||
break :outer;
|
||||
}
|
||||
inner: {
|
||||
@ -1109,22 +1120,29 @@ fn writeStub(self: *Zld, index: u32) !void {
|
||||
const displacement = math.divExact(u64, target_addr - new_this_addr, 4) catch |_| break :inner;
|
||||
const literal = math.cast(u18, displacement) catch |_| break :inner;
|
||||
// nop
|
||||
mem.writeIntLittle(u32, code[0..4], Arm64.nop().toU32());
|
||||
mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.nop().toU32());
|
||||
// ldr x16, literal
|
||||
mem.writeIntLittle(u32, code[4..8], Arm64.ldr(16, literal, 1).toU32());
|
||||
mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.ldr(.x16, .{
|
||||
.literal = literal,
|
||||
}).toU32());
|
||||
break :outer;
|
||||
}
|
||||
// Use adrp followed by ldr(immediate).
|
||||
const this_page = @intCast(i32, this_addr >> 12);
|
||||
const target_page = @intCast(i32, target_addr >> 12);
|
||||
const pages = @bitCast(u21, @intCast(i21, target_page - this_page));
|
||||
mem.writeIntLittle(u32, code[0..4], Arm64.adrp(16, pages).toU32());
|
||||
const pages = @intCast(i21, target_page - this_page);
|
||||
mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.adrp(.x16, pages).toU32());
|
||||
const narrowed = @truncate(u12, target_addr);
|
||||
const offset = try math.divExact(u12, narrowed, 8);
|
||||
mem.writeIntLittle(u32, code[4..8], Arm64.ldrq(16, 16, offset).toU32());
|
||||
mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.ldr(.x16, .{
|
||||
.register = .{
|
||||
.rn = .x16,
|
||||
.offset = aarch64.Instruction.LoadStoreOffset.imm(offset),
|
||||
},
|
||||
}).toU32());
|
||||
}
|
||||
// br x16
|
||||
mem.writeIntLittle(u32, code[8..12], Arm64.br(16).toU32());
|
||||
mem.writeIntLittle(u32, code[8..12], aarch64.Instruction.br(.x16).toU32());
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
@ -1160,9 +1178,11 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void {
|
||||
const displacement = try math.cast(i28, @intCast(i64, stub_helper.offset) - @intCast(i64, stub_off) - 4);
|
||||
const literal = @divExact(stub_size - @sizeOf(u32), 4);
|
||||
// ldr w16, literal
|
||||
mem.writeIntLittle(u32, code[0..4], Arm64.ldr(16, literal, 0).toU32());
|
||||
mem.writeIntLittle(u32, code[0..4], aarch64.Instruction.ldr(.w16, .{
|
||||
.literal = literal,
|
||||
}).toU32());
|
||||
// b disp
|
||||
mem.writeIntLittle(u32, code[4..8], Arm64.b(displacement).toU32());
|
||||
mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.b(displacement).toU32());
|
||||
mem.writeIntLittle(u32, code[8..12], 0x0); // Just a placeholder populated in `populateLazyBindOffsetsInStubHelper`.
|
||||
},
|
||||
else => unreachable,
|
||||
@ -1486,9 +1506,18 @@ fn doRelocs(self: *Zld) !void {
|
||||
.ARM64_RELOC_BRANCH26 => {
|
||||
assert(rel.r_length == 2);
|
||||
const inst = code[off..][0..4];
|
||||
const displacement = @intCast(i28, @intCast(i64, target_addr) - @intCast(i64, this_addr));
|
||||
var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Branch), inst);
|
||||
parsed.disp = @truncate(u26, @bitCast(u28, displacement) >> 2);
|
||||
const displacement = @intCast(
|
||||
i28,
|
||||
@intCast(i64, target_addr) - @intCast(i64, this_addr),
|
||||
);
|
||||
var parsed = mem.bytesAsValue(
|
||||
meta.TagPayload(
|
||||
aarch64.Instruction,
|
||||
aarch64.Instruction.UnconditionalBranchImmediate,
|
||||
),
|
||||
inst,
|
||||
);
|
||||
parsed.imm26 = @truncate(u26, @bitCast(u28, displacement) >> 2);
|
||||
},
|
||||
.ARM64_RELOC_PAGE21,
|
||||
.ARM64_RELOC_GOT_LOAD_PAGE21,
|
||||
@ -1501,7 +1530,13 @@ fn doRelocs(self: *Zld) !void {
|
||||
const target_page = @intCast(i32, ta >> 12);
|
||||
const pages = @bitCast(u21, @intCast(i21, target_page - this_page));
|
||||
log.debug(" | moving by {} pages", .{pages});
|
||||
var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Address), inst);
|
||||
var parsed = mem.bytesAsValue(
|
||||
meta.TagPayload(
|
||||
aarch64.Instruction,
|
||||
aarch64.Instruction.PCRelativeAddress,
|
||||
),
|
||||
inst,
|
||||
);
|
||||
parsed.immhi = @truncate(u19, pages >> 2);
|
||||
parsed.immlo = @truncate(u2, pages);
|
||||
addend = null;
|
||||
@ -1510,17 +1545,29 @@ fn doRelocs(self: *Zld) !void {
|
||||
.ARM64_RELOC_GOT_LOAD_PAGEOFF12,
|
||||
=> {
|
||||
const inst = code[off..][0..4];
|
||||
if (Arm64.isArithmetic(inst)) {
|
||||
if (aarch64IsArithmetic(inst)) {
|
||||
log.debug(" | detected ADD opcode", .{});
|
||||
// add
|
||||
var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Add), inst);
|
||||
var parsed = mem.bytesAsValue(
|
||||
meta.TagPayload(
|
||||
aarch64.Instruction,
|
||||
aarch64.Instruction.AddSubtractImmediate,
|
||||
),
|
||||
inst,
|
||||
);
|
||||
const ta = if (addend) |a| target_addr + a else target_addr;
|
||||
const narrowed = @truncate(u12, ta);
|
||||
parsed.offset = narrowed;
|
||||
parsed.imm12 = narrowed;
|
||||
} else {
|
||||
log.debug(" | detected LDR/STR opcode", .{});
|
||||
// ldr/str
|
||||
var parsed = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.LoadRegister), inst);
|
||||
var parsed = mem.bytesAsValue(
|
||||
meta.TagPayload(
|
||||
aarch64.Instruction,
|
||||
aarch64.Instruction.LoadStoreRegister,
|
||||
),
|
||||
inst,
|
||||
);
|
||||
const ta = if (addend) |a| target_addr + a else target_addr;
|
||||
const narrowed = @truncate(u12, ta);
|
||||
const offset: u12 = blk: {
|
||||
@ -1541,27 +1588,43 @@ fn doRelocs(self: *Zld) !void {
|
||||
addend = null;
|
||||
},
|
||||
.ARM64_RELOC_TLVP_LOAD_PAGEOFF12 => {
|
||||
// TODO why is this necessary?
|
||||
const RegInfo = struct {
|
||||
rt: u5,
|
||||
rd: u5,
|
||||
rn: u5,
|
||||
size: u1,
|
||||
};
|
||||
const inst = code[off..][0..4];
|
||||
const parsed: RegInfo = blk: {
|
||||
if (Arm64.isArithmetic(inst)) {
|
||||
const curr = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.Add), inst);
|
||||
break :blk .{ .rt = curr.rt, .rn = curr.rn, .size = curr.size };
|
||||
if (aarch64IsArithmetic(inst)) {
|
||||
const curr = mem.bytesAsValue(
|
||||
meta.TagPayload(
|
||||
aarch64.Instruction,
|
||||
aarch64.Instruction.AddSubtractImmediate,
|
||||
),
|
||||
inst,
|
||||
);
|
||||
break :blk .{ .rd = curr.rd, .rn = curr.rn, .size = curr.sf };
|
||||
} else {
|
||||
const curr = mem.bytesAsValue(meta.TagPayload(Arm64, Arm64.LoadRegister), inst);
|
||||
break :blk .{ .rt = curr.rt, .rn = curr.rn, .size = @truncate(u1, curr.size) };
|
||||
const curr = mem.bytesAsValue(
|
||||
meta.TagPayload(
|
||||
aarch64.Instruction,
|
||||
aarch64.Instruction.LoadStoreRegister,
|
||||
),
|
||||
inst,
|
||||
);
|
||||
break :blk .{ .rd = curr.rt, .rn = curr.rn, .size = @truncate(u1, curr.size) };
|
||||
}
|
||||
};
|
||||
const ta = if (addend) |a| target_addr + a else target_addr;
|
||||
const narrowed = @truncate(u12, ta);
|
||||
log.debug(" | rewriting TLV access to ADD opcode", .{});
|
||||
// For TLV, we always generate an add instruction.
|
||||
mem.writeIntLittle(u32, inst, Arm64.add(parsed.rt, parsed.rn, narrowed, parsed.size).toU32());
|
||||
mem.writeIntLittle(u32, inst, aarch64.Instruction.add(
|
||||
@intToEnum(aarch64.Register, parsed.rd),
|
||||
@intToEnum(aarch64.Register, parsed.rn),
|
||||
narrowed,
|
||||
false,
|
||||
).toU32());
|
||||
},
|
||||
.ARM64_RELOC_SUBTRACTOR => {
|
||||
sub = @intCast(i64, target_addr);
|
||||
@ -2965,3 +3028,8 @@ fn isExtern(sym: *const macho.nlist_64) callconv(.Inline) bool {
|
||||
fn isWeakDef(sym: *const macho.nlist_64) callconv(.Inline) bool {
|
||||
return (sym.n_desc & macho.N_WEAK_DEF) != 0;
|
||||
}
|
||||
|
||||
fn aarch64IsArithmetic(inst: *const [4]u8) callconv(.Inline) bool {
|
||||
const group_decode = @truncate(u5, inst[3]);
|
||||
return ((group_decode >> 2) == 4);
|
||||
}
|
||||
|
@ -1,197 +0,0 @@
|
||||
const std = @import("std");
|
||||
const log = std.log.scoped(.reloc);
|
||||
|
||||
pub const Arm64 = union(enum) {
|
||||
Branch: packed struct {
|
||||
disp: u26,
|
||||
fixed: u5 = 0b00101,
|
||||
link: u1,
|
||||
},
|
||||
BranchRegister: packed struct {
|
||||
_1: u5 = 0b0000_0,
|
||||
reg: u5,
|
||||
_2: u11 = 0b1111_1000_000,
|
||||
link: u1,
|
||||
_3: u10 = 0b1101_0110_00,
|
||||
},
|
||||
Address: packed struct {
|
||||
reg: u5,
|
||||
immhi: u19,
|
||||
_1: u5 = 0b10000,
|
||||
immlo: u2,
|
||||
page: u1,
|
||||
},
|
||||
LoadRegister: packed struct {
|
||||
rt: u5,
|
||||
rn: u5,
|
||||
offset: u12,
|
||||
opc: u2,
|
||||
_2: u2 = 0b01,
|
||||
v: u1,
|
||||
_1: u3 = 0b111,
|
||||
size: u2,
|
||||
},
|
||||
LoadLiteral: packed struct {
|
||||
reg: u5,
|
||||
literal: u19,
|
||||
_1: u6 = 0b011_0_00,
|
||||
size: u1,
|
||||
_2: u1 = 0b0,
|
||||
},
|
||||
Add: packed struct {
|
||||
rt: u5,
|
||||
rn: u5,
|
||||
offset: u12,
|
||||
_1: u9 = 0b0_0_100010_0,
|
||||
size: u1,
|
||||
},
|
||||
Nop: packed struct {
|
||||
fixed: u32 = 0b1101010100_0_00_011_0010_0000_000_11111,
|
||||
},
|
||||
|
||||
pub fn toU32(self: Arm64) u32 {
|
||||
const as_u32 = switch (self) {
|
||||
.Branch => |x| @bitCast(u32, x),
|
||||
.BranchRegister => |x| @bitCast(u32, x),
|
||||
.Address => |x| @bitCast(u32, x),
|
||||
.LoadRegister => |x| @bitCast(u32, x),
|
||||
.LoadLiteral => |x| @bitCast(u32, x),
|
||||
.Add => |x| @bitCast(u32, x),
|
||||
.Nop => |x| @bitCast(u32, x),
|
||||
};
|
||||
return as_u32;
|
||||
}
|
||||
|
||||
pub fn b(disp: i28) Arm64 {
|
||||
return Arm64{
|
||||
.Branch = .{
|
||||
.disp = @truncate(u26, @bitCast(u28, disp) >> 2),
|
||||
.link = 0,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn bl(disp: i28) Arm64 {
|
||||
return Arm64{
|
||||
.Branch = .{
|
||||
.disp = @truncate(u26, @bitCast(u28, disp) >> 2),
|
||||
.link = 1,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn br(reg: u5) Arm64 {
|
||||
return Arm64{
|
||||
.BranchRegister = .{
|
||||
.reg = reg,
|
||||
.link = 0,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn blr(reg: u5) Arm64 {
|
||||
return Arm64{
|
||||
.BranchRegister = .{
|
||||
.reg = reg,
|
||||
.link = 1,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn adr(reg: u5, disp: u21) Arm64 {
|
||||
return Arm64{
|
||||
.Address = .{
|
||||
.reg = reg,
|
||||
.immhi = @truncate(u19, disp >> 2),
|
||||
.immlo = @truncate(u2, disp),
|
||||
.page = 0,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn adrp(reg: u5, disp: u21) Arm64 {
|
||||
return Arm64{
|
||||
.Address = .{
|
||||
.reg = reg,
|
||||
.immhi = @truncate(u19, disp >> 2),
|
||||
.immlo = @truncate(u2, disp),
|
||||
.page = 1,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn ldr(reg: u5, literal: u19, size: u1) Arm64 {
|
||||
return Arm64{
|
||||
.LoadLiteral = .{
|
||||
.reg = reg,
|
||||
.literal = literal,
|
||||
.size = size,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn add(rt: u5, rn: u5, offset: u12, size: u1) Arm64 {
|
||||
return Arm64{
|
||||
.Add = .{
|
||||
.rt = rt,
|
||||
.rn = rn,
|
||||
.offset = offset,
|
||||
.size = size,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn ldrq(rt: u5, rn: u5, offset: u12) Arm64 {
|
||||
return Arm64{
|
||||
.LoadRegister = .{
|
||||
.rt = rt,
|
||||
.rn = rn,
|
||||
.offset = offset,
|
||||
.opc = 0b01,
|
||||
.v = 0b0,
|
||||
.size = 0b11,
|
||||
},
|
||||
};
|
||||
}
|
||||
pub fn ldrh(rt: u5, rn: u5, offset: u12) Arm64 {
|
||||
return Arm64{
|
||||
.LoadRegister = .{
|
||||
.rt = rt,
|
||||
.rn = rn,
|
||||
.offset = offset,
|
||||
.opc = 0b01,
|
||||
.v = 0b0,
|
||||
.size = 0b01,
|
||||
},
|
||||
};
|
||||
}
|
||||
pub fn ldrb(rt: u5, rn: u5, offset: u12) Arm64 {
|
||||
return Arm64{
|
||||
.LoadRegister = .{
|
||||
.rt = rt,
|
||||
.rn = rn,
|
||||
.offset = offset,
|
||||
.opc = 0b01,
|
||||
.v = 0b0,
|
||||
.size = 0b00,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn nop() Arm64 {
|
||||
return Arm64{
|
||||
.Nop = .{},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isArithmetic(inst: *const [4]u8) bool {
|
||||
const group_decode = @truncate(u5, inst[3]);
|
||||
log.debug("{b}", .{group_decode});
|
||||
return ((group_decode >> 2) == 4);
|
||||
// if ((group_decode >> 2) == 4) {
|
||||
// log.debug("Arithmetic imm", .{});
|
||||
// } else if (((group_decode & 0b01010) >> 3) == 1) {
|
||||
// log.debug("Load/store", .{});
|
||||
// }
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user