mirror of
https://github.com/ziglang/zig.git
synced 2026-01-12 02:15:12 +00:00
107 lines
3.6 KiB
Zig
107 lines
3.6 KiB
Zig
pub inline fn isArithmeticOp(inst: *const [4]u8) bool {
|
|
const group_decode = @as(u5, @truncate(inst[3]));
|
|
return ((group_decode >> 2) == 4);
|
|
}
|
|
|
|
pub const PageOffsetInstKind = enum {
|
|
arithmetic,
|
|
load_store_8,
|
|
load_store_16,
|
|
load_store_32,
|
|
load_store_64,
|
|
load_store_128,
|
|
};
|
|
|
|
pub fn classifyInst(code: *const [4]u8) PageOffsetInstKind {
|
|
if (isArithmeticOp(code)) return .arithmetic;
|
|
const inst = Instruction{
|
|
.load_store_register = mem.bytesToValue(std.meta.TagPayload(
|
|
Instruction,
|
|
Instruction.load_store_register,
|
|
), code),
|
|
};
|
|
return switch (inst.load_store_register.size) {
|
|
0 => if (inst.load_store_register.v == 1) .load_store_128 else .load_store_8,
|
|
1 => .load_store_16,
|
|
2 => .load_store_32,
|
|
3 => .load_store_64,
|
|
};
|
|
}
|
|
|
|
pub fn calcPageOffset(kind: PageOffsetInstKind, taddr: u64) !u12 {
|
|
const narrowed = @as(u12, @truncate(taddr));
|
|
return switch (kind) {
|
|
.arithmetic, .load_store_8 => narrowed,
|
|
.load_store_16 => try math.divExact(u12, narrowed, 2),
|
|
.load_store_32 => try math.divExact(u12, narrowed, 4),
|
|
.load_store_64 => try math.divExact(u12, narrowed, 8),
|
|
.load_store_128 => try math.divExact(u12, narrowed, 16),
|
|
};
|
|
}
|
|
|
|
pub fn writePageOffset(kind: PageOffsetInstKind, taddr: u64, code: *[4]u8) !void {
|
|
const value = try calcPageOffset(kind, taddr);
|
|
switch (kind) {
|
|
.arithmetic => {
|
|
var inst = Instruction{
|
|
.add_subtract_immediate = mem.bytesToValue(std.meta.TagPayload(
|
|
Instruction,
|
|
Instruction.add_subtract_immediate,
|
|
), code),
|
|
};
|
|
inst.add_subtract_immediate.imm12 = value;
|
|
mem.writeInt(u32, code, inst.toU32(), .little);
|
|
},
|
|
else => {
|
|
var inst: Instruction = .{
|
|
.load_store_register = mem.bytesToValue(std.meta.TagPayload(
|
|
Instruction,
|
|
Instruction.load_store_register,
|
|
), code),
|
|
};
|
|
inst.load_store_register.offset = value;
|
|
mem.writeInt(u32, code, inst.toU32(), .little);
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn calcNumberOfPages(saddr: u64, taddr: u64) error{Overflow}!i21 {
|
|
const spage = math.cast(i32, saddr >> 12) orelse return error.Overflow;
|
|
const tpage = math.cast(i32, taddr >> 12) orelse return error.Overflow;
|
|
const pages = math.cast(i21, tpage - spage) orelse return error.Overflow;
|
|
return pages;
|
|
}
|
|
|
|
pub fn writePages(pages: u21, code: *[4]u8) !void {
|
|
var inst = Instruction{
|
|
.pc_relative_address = mem.bytesToValue(std.meta.TagPayload(
|
|
Instruction,
|
|
Instruction.pc_relative_address,
|
|
), code),
|
|
};
|
|
inst.pc_relative_address.immhi = @as(u19, @truncate(pages >> 2));
|
|
inst.pc_relative_address.immlo = @as(u2, @truncate(pages));
|
|
mem.writeInt(u32, code, inst.toU32(), .little);
|
|
}
|
|
|
|
pub fn writeBranchImm(disp: i28, code: *[4]u8) !void {
|
|
var inst = Instruction{
|
|
.unconditional_branch_immediate = mem.bytesToValue(std.meta.TagPayload(
|
|
Instruction,
|
|
Instruction.unconditional_branch_immediate,
|
|
), code),
|
|
};
|
|
inst.unconditional_branch_immediate.imm26 = @as(u26, @truncate(@as(u28, @bitCast(disp >> 2))));
|
|
mem.writeInt(u32, code, inst.toU32(), .little);
|
|
}
|
|
|
|
const assert = std.debug.assert;
|
|
const bits = @import("../arch/aarch64/bits.zig");
|
|
const builtin = @import("builtin");
|
|
const math = std.math;
|
|
const mem = std.mem;
|
|
const std = @import("std");
|
|
|
|
pub const Instruction = bits.Instruction;
|
|
pub const Register = bits.Register;
|