mirror of
https://github.com/ziglang/zig.git
synced 2026-02-15 05:48:31 +00:00
Merge remote-tracking branch 'origin/zstd' into wrangle-writer-buffering
This commit is contained in:
commit
45a35d448e
@ -348,8 +348,9 @@ fn buildWasmBinary(
|
||||
};
|
||||
}
|
||||
|
||||
if (poller.reader(.stderr).buffer.len > 0) {
|
||||
std.debug.print("{s}", .{poller.reader(.stderr).buffered()});
|
||||
const stderr = poller.reader(.stderr);
|
||||
if (stderr.bufferedLen() > 0) {
|
||||
std.debug.print("{s}", .{stderr.buffered()});
|
||||
}
|
||||
|
||||
// Send EOF to stdin.
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
//! Use `zig init --strip` next time to generate a project without comments.
|
||||
const std = @import("std");
|
||||
|
||||
// Although this function looks imperative, it does not perform the build
|
||||
|
||||
@ -373,11 +373,11 @@ pub fn discard(self: Self) anyerror!u64 {
|
||||
}
|
||||
|
||||
/// Helper for bridging to the new `Reader` API while upgrading.
|
||||
pub fn adaptToNewApi(self: *const Self) Adapter {
|
||||
pub fn adaptToNewApi(self: *const Self, buffer: []u8) Adapter {
|
||||
return .{
|
||||
.derp_reader = self.*,
|
||||
.new_interface = .{
|
||||
.buffer = &.{},
|
||||
.buffer = buffer,
|
||||
.vtable = &.{ .stream = Adapter.stream },
|
||||
.seek = 0,
|
||||
.end = 0,
|
||||
|
||||
@ -185,6 +185,32 @@ pub fn streamExact64(r: *Reader, w: *Writer, n: u64) StreamError!void {
|
||||
while (remaining != 0) remaining -= try r.stream(w, .limited64(remaining));
|
||||
}
|
||||
|
||||
/// "Pump" exactly `n` bytes from the reader to the writer.
|
||||
///
|
||||
/// When draining `w`, ensures that at least `preserve_len` bytes remain
|
||||
/// buffered.
|
||||
///
|
||||
/// Asserts `Writer.buffer` capacity exceeds `preserve_len`.
|
||||
pub fn streamExactPreserve(r: *Reader, w: *Writer, preserve_len: usize, n: usize) StreamError!void {
|
||||
if (w.end + n <= w.buffer.len) {
|
||||
@branchHint(.likely);
|
||||
return streamExact(r, w, n);
|
||||
}
|
||||
// If `n` is large, we can ignore `preserve_len` up to a point.
|
||||
var remaining = n;
|
||||
while (remaining > preserve_len) {
|
||||
assert(remaining != 0);
|
||||
remaining -= try r.stream(w, .limited(remaining - preserve_len));
|
||||
if (w.end + remaining <= w.buffer.len) return streamExact(r, w, remaining);
|
||||
}
|
||||
// All the next bytes received must be preserved.
|
||||
if (preserve_len < w.end) {
|
||||
@memmove(w.buffer[0..preserve_len], w.buffer[w.end - preserve_len ..][0..preserve_len]);
|
||||
w.end = preserve_len;
|
||||
}
|
||||
return streamExact(r, w, remaining);
|
||||
}
|
||||
|
||||
/// "Pump" data from the reader to the writer, handling `error.EndOfStream` as
|
||||
/// a success case.
|
||||
///
|
||||
@ -240,7 +266,7 @@ pub fn allocRemaining(r: *Reader, gpa: Allocator, limit: Limit) LimitedAllocErro
|
||||
/// such case, the next byte that would be read will be the first one to exceed
|
||||
/// `limit`, and all preceeding bytes have been appended to `list`.
|
||||
///
|
||||
/// Asserts `buffer` has nonzero capacity.
|
||||
/// If `limit` is not `Limit.unlimited`, asserts `buffer` has nonzero capacity.
|
||||
///
|
||||
/// See also:
|
||||
/// * `allocRemaining`
|
||||
@ -251,7 +277,7 @@ pub fn appendRemaining(
|
||||
list: *std.ArrayListAlignedUnmanaged(u8, alignment),
|
||||
limit: Limit,
|
||||
) LimitedAllocError!void {
|
||||
assert(r.buffer.len != 0); // Needed to detect limit exceeded without losing data.
|
||||
if (limit != .unlimited) assert(r.buffer.len != 0); // Needed to detect limit exceeded without losing data.
|
||||
const buffer_contents = r.buffer[r.seek..r.end];
|
||||
const copy_len = limit.minInt(buffer_contents.len);
|
||||
try list.appendSlice(gpa, r.buffer[0..copy_len]);
|
||||
|
||||
@ -256,10 +256,10 @@ test "fixed buffer flush" {
|
||||
try testing.expectEqual(10, buffer[0]);
|
||||
}
|
||||
|
||||
/// Calls `VTable.drain` but hides the last `preserve_length` bytes from the
|
||||
/// Calls `VTable.drain` but hides the last `preserve_len` bytes from the
|
||||
/// implementation, keeping them buffered.
|
||||
pub fn drainPreserve(w: *Writer, preserve_length: usize) Error!void {
|
||||
const temp_end = w.end -| preserve_length;
|
||||
pub fn drainPreserve(w: *Writer, preserve_len: usize) Error!void {
|
||||
const temp_end = w.end -| preserve_len;
|
||||
const preserved = w.buffer[temp_end..w.end];
|
||||
w.end = temp_end;
|
||||
defer w.end += preserved.len;
|
||||
@ -310,24 +310,38 @@ pub fn writableSliceGreedy(w: *Writer, minimum_length: usize) Error![]u8 {
|
||||
}
|
||||
|
||||
/// Asserts the provided buffer has total capacity enough for `minimum_length`
|
||||
/// and `preserve_length` combined.
|
||||
/// and `preserve_len` combined.
|
||||
///
|
||||
/// Does not `advance` the buffer end position.
|
||||
///
|
||||
/// When draining the buffer, ensures that at least `preserve_length` bytes
|
||||
/// When draining the buffer, ensures that at least `preserve_len` bytes
|
||||
/// remain buffered.
|
||||
///
|
||||
/// If `preserve_length` is zero, this is equivalent to `writableSliceGreedy`.
|
||||
pub fn writableSliceGreedyPreserve(w: *Writer, preserve_length: usize, minimum_length: usize) Error![]u8 {
|
||||
assert(w.buffer.len >= preserve_length + minimum_length);
|
||||
/// If `preserve_len` is zero, this is equivalent to `writableSliceGreedy`.
|
||||
pub fn writableSliceGreedyPreserve(w: *Writer, preserve_len: usize, minimum_length: usize) Error![]u8 {
|
||||
assert(w.buffer.len >= preserve_len + minimum_length);
|
||||
while (w.buffer.len - w.end < minimum_length) {
|
||||
try drainPreserve(w, preserve_length);
|
||||
try drainPreserve(w, preserve_len);
|
||||
} else {
|
||||
@branchHint(.likely);
|
||||
return w.buffer[w.end..];
|
||||
}
|
||||
}
|
||||
|
||||
/// Asserts the provided buffer has total capacity enough for `len`.
|
||||
///
|
||||
/// Advances the buffer end position by `len`.
|
||||
///
|
||||
/// When draining the buffer, ensures that at least `preserve_len` bytes
|
||||
/// remain buffered.
|
||||
///
|
||||
/// If `preserve_len` is zero, this is equivalent to `writableSlice`.
|
||||
pub fn writableSlicePreserve(w: *Writer, preserve_len: usize, len: usize) Error![]u8 {
|
||||
const big_slice = try w.writableSliceGreedyPreserve(preserve_len, len);
|
||||
advance(w, len);
|
||||
return big_slice[0..len];
|
||||
}
|
||||
|
||||
pub const WritableVectorIterator = struct {
|
||||
first: []u8,
|
||||
middle: []const []u8 = &.{},
|
||||
@ -523,16 +537,16 @@ pub fn write(w: *Writer, bytes: []const u8) Error!usize {
|
||||
return w.vtable.drain(w, &.{bytes}, 1);
|
||||
}
|
||||
|
||||
/// Asserts `buffer` capacity exceeds `preserve_length`.
|
||||
pub fn writePreserve(w: *Writer, preserve_length: usize, bytes: []const u8) Error!usize {
|
||||
assert(preserve_length <= w.buffer.len);
|
||||
/// Asserts `buffer` capacity exceeds `preserve_len`.
|
||||
pub fn writePreserve(w: *Writer, preserve_len: usize, bytes: []const u8) Error!usize {
|
||||
assert(preserve_len <= w.buffer.len);
|
||||
if (w.end + bytes.len <= w.buffer.len) {
|
||||
@branchHint(.likely);
|
||||
@memcpy(w.buffer[w.end..][0..bytes.len], bytes);
|
||||
w.end += bytes.len;
|
||||
return bytes.len;
|
||||
}
|
||||
const temp_end = w.end -| preserve_length;
|
||||
const temp_end = w.end -| preserve_len;
|
||||
const preserved = w.buffer[temp_end..w.end];
|
||||
w.end = temp_end;
|
||||
defer w.end += preserved.len;
|
||||
@ -552,13 +566,13 @@ pub fn writeAll(w: *Writer, bytes: []const u8) Error!void {
|
||||
/// Calls `drain` as many times as necessary such that all of `bytes` are
|
||||
/// transferred.
|
||||
///
|
||||
/// When draining the buffer, ensures that at least `preserve_length` bytes
|
||||
/// When draining the buffer, ensures that at least `preserve_len` bytes
|
||||
/// remain buffered.
|
||||
///
|
||||
/// Asserts `buffer` capacity exceeds `preserve_length`.
|
||||
pub fn writeAllPreserve(w: *Writer, preserve_length: usize, bytes: []const u8) Error!void {
|
||||
/// Asserts `buffer` capacity exceeds `preserve_len`.
|
||||
pub fn writeAllPreserve(w: *Writer, preserve_len: usize, bytes: []const u8) Error!void {
|
||||
var index: usize = 0;
|
||||
while (index < bytes.len) index += try w.writePreserve(preserve_length, bytes[index..]);
|
||||
while (index < bytes.len) index += try w.writePreserve(preserve_len, bytes[index..]);
|
||||
}
|
||||
|
||||
/// Renders fmt string with args, calling `writer` with slices of bytes.
|
||||
@ -761,11 +775,11 @@ pub fn writeByte(w: *Writer, byte: u8) Error!void {
|
||||
}
|
||||
}
|
||||
|
||||
/// When draining the buffer, ensures that at least `preserve_length` bytes
|
||||
/// When draining the buffer, ensures that at least `preserve_len` bytes
|
||||
/// remain buffered.
|
||||
pub fn writeBytePreserve(w: *Writer, preserve_length: usize, byte: u8) Error!void {
|
||||
pub fn writeBytePreserve(w: *Writer, preserve_len: usize, byte: u8) Error!void {
|
||||
while (w.buffer.len - w.end == 0) {
|
||||
try drainPreserve(w, preserve_length);
|
||||
try drainPreserve(w, preserve_len);
|
||||
} else {
|
||||
@branchHint(.likely);
|
||||
w.buffer[w.end] = byte;
|
||||
@ -788,10 +802,42 @@ test splatByteAll {
|
||||
try testing.expectEqualStrings("7" ** 45, aw.writer.buffered());
|
||||
}
|
||||
|
||||
pub fn splatBytePreserve(w: *Writer, preserve_len: usize, byte: u8, n: usize) Error!void {
|
||||
const new_end = w.end + n;
|
||||
if (new_end <= w.buffer.len) {
|
||||
@memset(w.buffer[w.end..][0..n], byte);
|
||||
w.end = new_end;
|
||||
return;
|
||||
}
|
||||
// If `n` is large, we can ignore `preserve_len` up to a point.
|
||||
var remaining = n;
|
||||
while (remaining > preserve_len) {
|
||||
assert(remaining != 0);
|
||||
remaining -= try splatByte(w, byte, remaining - preserve_len);
|
||||
if (w.end + remaining <= w.buffer.len) {
|
||||
@memset(w.buffer[w.end..][0..remaining], byte);
|
||||
w.end += remaining;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// All the next bytes received must be preserved.
|
||||
if (preserve_len < w.end) {
|
||||
@memmove(w.buffer[0..preserve_len], w.buffer[w.end - preserve_len ..][0..preserve_len]);
|
||||
w.end = preserve_len;
|
||||
}
|
||||
while (remaining > 0) remaining -= try w.splatByte(byte, remaining);
|
||||
}
|
||||
|
||||
/// Writes the same byte many times, allowing short writes.
|
||||
///
|
||||
/// Does maximum of one underlying `VTable.drain`.
|
||||
pub fn splatByte(w: *Writer, byte: u8, n: usize) Error!usize {
|
||||
if (w.end + n <= w.buffer.len) {
|
||||
@branchHint(.likely);
|
||||
@memset(w.buffer[w.end..][0..n], byte);
|
||||
w.end += n;
|
||||
return n;
|
||||
}
|
||||
return writeSplat(w, &.{&.{byte}}, n);
|
||||
}
|
||||
|
||||
@ -801,9 +847,10 @@ pub fn splatBytesAll(w: *Writer, bytes: []const u8, splat: usize) Error!void {
|
||||
var remaining_bytes: usize = bytes.len * splat;
|
||||
remaining_bytes -= try w.splatBytes(bytes, splat);
|
||||
while (remaining_bytes > 0) {
|
||||
const leftover = remaining_bytes % bytes.len;
|
||||
const buffers: [2][]const u8 = .{ bytes[bytes.len - leftover ..], bytes };
|
||||
remaining_bytes -= try w.writeSplat(&buffers, splat);
|
||||
const leftover_splat = remaining_bytes / bytes.len;
|
||||
const leftover_bytes = remaining_bytes % bytes.len;
|
||||
const buffers: [2][]const u8 = .{ bytes[bytes.len - leftover_bytes ..], bytes };
|
||||
remaining_bytes -= try w.writeSplat(&buffers, leftover_splat);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@ pub fn Decompress(comptime ReaderType: type) type {
|
||||
|
||||
var check: Check = undefined;
|
||||
const hash_a = blk: {
|
||||
var hasher = std.compress.hashedReader(source, Crc32.init());
|
||||
var hasher = hashedReader(source, Crc32.init());
|
||||
try readStreamFlags(hasher.reader(), &check);
|
||||
break :blk hasher.hasher.final();
|
||||
};
|
||||
@ -80,7 +80,7 @@ pub fn Decompress(comptime ReaderType: type) type {
|
||||
return r;
|
||||
|
||||
const index_size = blk: {
|
||||
var hasher = std.compress.hashedReader(self.in_reader, Crc32.init());
|
||||
var hasher = hashedReader(self.in_reader, Crc32.init());
|
||||
hasher.hasher.update(&[1]u8{0x00});
|
||||
|
||||
var counter = std.io.countingReader(hasher.reader());
|
||||
@ -115,7 +115,7 @@ pub fn Decompress(comptime ReaderType: type) type {
|
||||
const hash_a = try self.in_reader.readInt(u32, .little);
|
||||
|
||||
const hash_b = blk: {
|
||||
var hasher = std.compress.hashedReader(self.in_reader, Crc32.init());
|
||||
var hasher = hashedReader(self.in_reader, Crc32.init());
|
||||
const hashed_reader = hasher.reader();
|
||||
|
||||
const backward_size = (@as(u64, try hashed_reader.readInt(u32, .little)) + 1) * 4;
|
||||
@ -140,6 +140,33 @@ pub fn Decompress(comptime ReaderType: type) type {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn HashedReader(ReaderType: type, HasherType: type) type {
|
||||
return struct {
|
||||
child_reader: ReaderType,
|
||||
hasher: HasherType,
|
||||
|
||||
pub const Error = ReaderType.Error;
|
||||
pub const Reader = std.io.GenericReader(*@This(), Error, read);
|
||||
|
||||
pub fn read(self: *@This(), buf: []u8) Error!usize {
|
||||
const amt = try self.child_reader.read(buf);
|
||||
self.hasher.update(buf[0..amt]);
|
||||
return amt;
|
||||
}
|
||||
|
||||
pub fn reader(self: *@This()) Reader {
|
||||
return .{ .context = self };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn hashedReader(
|
||||
reader: anytype,
|
||||
hasher: anytype,
|
||||
) HashedReader(@TypeOf(reader), @TypeOf(hasher)) {
|
||||
return .{ .child_reader = reader, .hasher = hasher };
|
||||
}
|
||||
|
||||
test {
|
||||
_ = @import("xz/test.zig");
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ pub fn Decoder(comptime ReaderType: type) type {
|
||||
|
||||
// Block Header
|
||||
{
|
||||
var header_hasher = std.compress.hashedReader(block_reader, Crc32.init());
|
||||
var header_hasher = xz.hashedReader(block_reader, Crc32.init());
|
||||
const header_reader = header_hasher.reader();
|
||||
|
||||
const header_size = @as(u64, try header_reader.readByte()) * 4;
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
const std = @import("../std.zig");
|
||||
const assert = std.debug.assert;
|
||||
|
||||
pub const Decompress = @import("zstd/Decompress.zig");
|
||||
|
||||
/// Recommended amount by the standard. Lower than this may result in inability
|
||||
/// to decompress common streams.
|
||||
pub const default_window_len = 8 * 1024 * 1024;
|
||||
|
||||
pub const Decompress = @import("zstd/Decompress.zig");
|
||||
|
||||
pub const block_size_max = 1 << 17;
|
||||
|
||||
pub const literals_length_default_distribution = [36]i16{
|
||||
@ -85,7 +84,7 @@ fn testDecompress(gpa: std.mem.Allocator, compressed: []const u8) ![]u8 {
|
||||
|
||||
var in: std.io.Reader = .fixed(compressed);
|
||||
var zstd_stream: Decompress = .init(&in, &.{}, .{});
|
||||
try zstd_stream.interface.appendRemaining(gpa, null, &out, .unlimited);
|
||||
try zstd_stream.reader.appendRemaining(gpa, null, &out, .unlimited);
|
||||
|
||||
return out.toOwnedSlice(gpa);
|
||||
}
|
||||
@ -108,7 +107,7 @@ fn testExpectDecompressError(err: anyerror, compressed: []const u8) !void {
|
||||
var zstd_stream: Decompress = .init(&in, &.{}, .{});
|
||||
try std.testing.expectError(
|
||||
error.ReadFailed,
|
||||
zstd_stream.interface.appendRemaining(gpa, null, &out, .unlimited),
|
||||
zstd_stream.reader.appendRemaining(gpa, null, &out, .unlimited),
|
||||
);
|
||||
try std.testing.expectError(err, zstd_stream.err orelse {});
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ input: *Reader,
|
||||
reader: Reader,
|
||||
state: State,
|
||||
verify_checksum: bool,
|
||||
window_len: u32,
|
||||
err: ?Error = null,
|
||||
|
||||
const State = union(enum) {
|
||||
@ -22,11 +23,16 @@ const State = union(enum) {
|
||||
frame: Frame,
|
||||
checksum: ?u32,
|
||||
decompressed_size: usize,
|
||||
decode: Frame.Zstandard.Decode,
|
||||
};
|
||||
};
|
||||
|
||||
pub const Options = struct {
|
||||
verify_checksum: bool = true,
|
||||
/// Verifying checksums is not implemented yet and will cause a panic if
|
||||
/// you set this to true.
|
||||
verify_checksum: bool = false,
|
||||
/// Affects the minimum capacity of the provided buffer.
|
||||
window_len: u32 = zstd.default_window_len,
|
||||
};
|
||||
|
||||
pub const Error = error{
|
||||
@ -63,11 +69,14 @@ pub const Error = error{
|
||||
WindowSizeUnknown,
|
||||
};
|
||||
|
||||
/// If buffer that is written to is not big enough, some streams will fail with
|
||||
/// `error.OutputBufferUndersize`. A safe value is `zstd.default_window_len * 2`.
|
||||
pub fn init(input: *Reader, buffer: []u8, options: Options) Decompress {
|
||||
return .{
|
||||
.input = input,
|
||||
.state = .new_frame,
|
||||
.verify_checksum = options.verify_checksum,
|
||||
.window_len = options.window_len,
|
||||
.reader = .{
|
||||
.vtable = &.{ .stream = stream },
|
||||
.buffer = buffer,
|
||||
@ -130,6 +139,7 @@ fn initFrame(d: *Decompress, window_size_max: usize, magic: Frame.Magic) !void {
|
||||
.frame = try Frame.init(header, window_size_max, d.verify_checksum),
|
||||
.checksum = null,
|
||||
.decompressed_size = 0,
|
||||
.decode = .init,
|
||||
} };
|
||||
},
|
||||
.skippable => {
|
||||
@ -139,11 +149,11 @@ fn initFrame(d: *Decompress, window_size_max: usize, magic: Frame.Magic) !void {
|
||||
}
|
||||
}
|
||||
|
||||
fn readInFrame(d: *Decompress, bw: *Writer, limit: Limit, state: *State.InFrame) !usize {
|
||||
fn readInFrame(d: *Decompress, w: *Writer, limit: Limit, state: *State.InFrame) !usize {
|
||||
const in = d.input;
|
||||
const window_len = d.window_len;
|
||||
|
||||
const header_bytes = try in.takeArray(3);
|
||||
const block_header: Frame.Zstandard.Block.Header = @bitCast(header_bytes.*);
|
||||
const block_header = try in.takeStruct(Frame.Zstandard.Block.Header, .little);
|
||||
const block_size = block_header.size;
|
||||
const frame_block_size_max = state.frame.block_size_max;
|
||||
if (frame_block_size_max < block_size) return error.BlockOversize;
|
||||
@ -151,49 +161,47 @@ fn readInFrame(d: *Decompress, bw: *Writer, limit: Limit, state: *State.InFrame)
|
||||
var bytes_written: usize = 0;
|
||||
switch (block_header.type) {
|
||||
.raw => {
|
||||
try in.readAll(bw, .limited(block_size));
|
||||
try in.streamExactPreserve(w, window_len, block_size);
|
||||
bytes_written = block_size;
|
||||
},
|
||||
.rle => {
|
||||
const byte = try in.takeByte();
|
||||
try bw.splatByteAll(byte, block_size);
|
||||
try w.splatBytePreserve(window_len, byte, block_size);
|
||||
bytes_written = block_size;
|
||||
},
|
||||
.compressed => {
|
||||
var literal_fse_buffer: [zstd.table_size_max.literal]Table.Fse = undefined;
|
||||
var match_fse_buffer: [zstd.table_size_max.match]Table.Fse = undefined;
|
||||
var offset_fse_buffer: [zstd.table_size_max.offset]Table.Fse = undefined;
|
||||
var literals_buffer: [zstd.block_size_max]u8 = undefined;
|
||||
var sequence_buffer: [zstd.block_size_max]u8 = undefined;
|
||||
var decode: Frame.Zstandard.Decode = .init(&literal_fse_buffer, &match_fse_buffer, &offset_fse_buffer);
|
||||
var remaining: Limit = .limited(block_size);
|
||||
const literals = try LiteralsSection.decode(in, &remaining, &literals_buffer);
|
||||
const sequences_header = try SequencesSection.Header.decode(in, &remaining);
|
||||
|
||||
const decode = &state.decode;
|
||||
try decode.prepare(in, &remaining, literals, sequences_header);
|
||||
|
||||
{
|
||||
if (sequence_buffer.len < @intFromEnum(remaining))
|
||||
return error.SequenceBufferUndersize;
|
||||
const seq_slice = remaining.slice(&sequence_buffer);
|
||||
try in.readSlice(seq_slice);
|
||||
try in.readSliceAll(seq_slice);
|
||||
var bit_stream = try ReverseBitReader.init(seq_slice);
|
||||
|
||||
if (sequences_header.sequence_count > 0) {
|
||||
try decode.readInitialFseState(&bit_stream);
|
||||
|
||||
// Ensures the following calls to `decodeSequence` will not flush.
|
||||
if (frame_block_size_max > bw.buffer.len) return error.OutputBufferUndersize;
|
||||
const dest = (try bw.writableSliceGreedy(frame_block_size_max))[0..frame_block_size_max];
|
||||
if (window_len + frame_block_size_max > w.buffer.len) return error.OutputBufferUndersize;
|
||||
const dest = (try w.writableSliceGreedyPreserve(window_len, frame_block_size_max))[0..frame_block_size_max];
|
||||
const write_pos = dest.ptr - w.buffer.ptr;
|
||||
for (0..sequences_header.sequence_count - 1) |_| {
|
||||
bytes_written += try decode.decodeSequence(dest, bytes_written, &bit_stream);
|
||||
bytes_written += try decode.decodeSequence(w.buffer, write_pos + bytes_written, &bit_stream);
|
||||
try decode.updateState(.literal, &bit_stream);
|
||||
try decode.updateState(.match, &bit_stream);
|
||||
try decode.updateState(.offset, &bit_stream);
|
||||
}
|
||||
bytes_written += try decode.decodeSequence(dest, bytes_written, &bit_stream);
|
||||
bytes_written += try decode.decodeSequence(w.buffer, write_pos + bytes_written, &bit_stream);
|
||||
if (bytes_written > dest.len) return error.MalformedSequence;
|
||||
bw.advance(bytes_written);
|
||||
w.advance(bytes_written);
|
||||
}
|
||||
|
||||
if (!bit_stream.isEmpty()) {
|
||||
@ -203,7 +211,7 @@ fn readInFrame(d: *Decompress, bw: *Writer, limit: Limit, state: *State.InFrame)
|
||||
|
||||
if (decode.literal_written_count < literals.header.regenerated_size) {
|
||||
const len = literals.header.regenerated_size - decode.literal_written_count;
|
||||
try decode.decodeLiterals(bw, len);
|
||||
try decode.decodeLiterals(w, len);
|
||||
decode.literal_written_count += len;
|
||||
bytes_written += len;
|
||||
}
|
||||
@ -216,11 +224,6 @@ fn readInFrame(d: *Decompress, bw: *Writer, limit: Limit, state: *State.InFrame)
|
||||
}
|
||||
|
||||
if (bytes_written > frame_block_size_max) return error.BlockOversize;
|
||||
|
||||
state.decompressed_size += bytes_written;
|
||||
if (state.frame.content_size) |size| {
|
||||
if (state.decompressed_size > size) return error.MalformedFrame;
|
||||
}
|
||||
},
|
||||
.reserved => return error.ReservedBlock,
|
||||
}
|
||||
@ -232,6 +235,8 @@ fn readInFrame(d: *Decompress, bw: *Writer, limit: Limit, state: *State.InFrame)
|
||||
}
|
||||
}
|
||||
|
||||
state.decompressed_size += bytes_written;
|
||||
|
||||
if (block_header.last) {
|
||||
if (state.frame.has_checksum) {
|
||||
const expected_checksum = try in.takeInt(u32, .little);
|
||||
@ -246,6 +251,8 @@ fn readInFrame(d: *Decompress, bw: *Writer, limit: Limit, state: *State.InFrame)
|
||||
}
|
||||
}
|
||||
d.state = .new_frame;
|
||||
} else if (state.frame.content_size) |content_size| {
|
||||
if (state.decompressed_size > content_size) return error.MalformedFrame;
|
||||
}
|
||||
|
||||
return bytes_written;
|
||||
@ -367,9 +374,9 @@ pub const Frame = struct {
|
||||
match: StateData(9),
|
||||
literal: StateData(9),
|
||||
|
||||
offset_fse_buffer: []Table.Fse,
|
||||
match_fse_buffer: []Table.Fse,
|
||||
literal_fse_buffer: []Table.Fse,
|
||||
literal_fse_buffer: [zstd.table_size_max.literal]Table.Fse,
|
||||
match_fse_buffer: [zstd.table_size_max.match]Table.Fse,
|
||||
offset_fse_buffer: [zstd.table_size_max.offset]Table.Fse,
|
||||
|
||||
fse_tables_undefined: bool,
|
||||
|
||||
@ -391,36 +398,30 @@ pub const Frame = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn init(
|
||||
literal_fse_buffer: []Table.Fse,
|
||||
match_fse_buffer: []Table.Fse,
|
||||
offset_fse_buffer: []Table.Fse,
|
||||
) Decode {
|
||||
return .{
|
||||
.repeat_offsets = .{
|
||||
zstd.start_repeated_offset_1,
|
||||
zstd.start_repeated_offset_2,
|
||||
zstd.start_repeated_offset_3,
|
||||
},
|
||||
const init: Decode = .{
|
||||
.repeat_offsets = .{
|
||||
zstd.start_repeated_offset_1,
|
||||
zstd.start_repeated_offset_2,
|
||||
zstd.start_repeated_offset_3,
|
||||
},
|
||||
|
||||
.offset = undefined,
|
||||
.match = undefined,
|
||||
.literal = undefined,
|
||||
.offset = undefined,
|
||||
.match = undefined,
|
||||
.literal = undefined,
|
||||
|
||||
.literal_fse_buffer = literal_fse_buffer,
|
||||
.match_fse_buffer = match_fse_buffer,
|
||||
.offset_fse_buffer = offset_fse_buffer,
|
||||
.literal_fse_buffer = undefined,
|
||||
.match_fse_buffer = undefined,
|
||||
.offset_fse_buffer = undefined,
|
||||
|
||||
.fse_tables_undefined = true,
|
||||
.fse_tables_undefined = true,
|
||||
|
||||
.literal_written_count = 0,
|
||||
.literal_header = undefined,
|
||||
.literal_streams = undefined,
|
||||
.literal_stream_reader = undefined,
|
||||
.literal_stream_index = undefined,
|
||||
.huffman_tree = null,
|
||||
};
|
||||
}
|
||||
.literal_written_count = 0,
|
||||
.literal_header = undefined,
|
||||
.literal_streams = undefined,
|
||||
.literal_stream_reader = undefined,
|
||||
.literal_stream_index = undefined,
|
||||
.huffman_tree = null,
|
||||
};
|
||||
|
||||
pub const PrepareError = error{
|
||||
/// the (reversed) literal bitstream's first byte does not have any bits set
|
||||
@ -502,12 +503,12 @@ pub const Frame = struct {
|
||||
return self.repeat_offsets[0];
|
||||
}
|
||||
|
||||
const DataType = enum { offset, match, literal };
|
||||
const WhichFse = enum { offset, match, literal };
|
||||
|
||||
/// TODO: don't use `@field`
|
||||
fn updateState(
|
||||
self: *Decode,
|
||||
comptime choice: DataType,
|
||||
comptime choice: WhichFse,
|
||||
bit_reader: *ReverseBitReader,
|
||||
) error{ MalformedFseBits, EndOfStream }!void {
|
||||
switch (@field(self, @tagName(choice)).table) {
|
||||
@ -537,7 +538,7 @@ pub const Frame = struct {
|
||||
self: *Decode,
|
||||
in: *Reader,
|
||||
remaining: *Limit,
|
||||
comptime choice: DataType,
|
||||
comptime choice: WhichFse,
|
||||
mode: SequencesSection.Header.Mode,
|
||||
) !void {
|
||||
const field_name = @tagName(choice);
|
||||
@ -564,10 +565,10 @@ pub const Frame = struct {
|
||||
&bit_reader,
|
||||
@field(zstd.table_symbol_count_max, field_name),
|
||||
@field(zstd.table_accuracy_log_max, field_name),
|
||||
@field(self, field_name ++ "_fse_buffer"),
|
||||
&@field(self, field_name ++ "_fse_buffer"),
|
||||
);
|
||||
@field(self, field_name).table = .{
|
||||
.fse = @field(self, field_name ++ "_fse_buffer")[0..table_size],
|
||||
.fse = (&@field(self, field_name ++ "_fse_buffer"))[0..table_size],
|
||||
};
|
||||
@field(self, field_name).accuracy_log = std.math.log2_int_ceil(usize, table_size);
|
||||
in.toss(bit_reader.index);
|
||||
@ -696,19 +697,19 @@ pub const Frame = struct {
|
||||
};
|
||||
}
|
||||
|
||||
/// Decode `len` bytes of literals into `dest`.
|
||||
fn decodeLiterals(self: *Decode, dest: *Writer, len: usize) !void {
|
||||
switch (self.literal_header.block_type) {
|
||||
/// Decode `len` bytes of literals into `w`.
|
||||
fn decodeLiterals(d: *Decode, w: *Writer, len: usize) !void {
|
||||
switch (d.literal_header.block_type) {
|
||||
.raw => {
|
||||
try dest.writeAll(self.literal_streams.one[self.literal_written_count..][0..len]);
|
||||
try w.writeAll(d.literal_streams.one[d.literal_written_count..][0..len]);
|
||||
},
|
||||
.rle => {
|
||||
try dest.splatByteAll(self.literal_streams.one[0], len);
|
||||
try w.splatByteAll(d.literal_streams.one[0], len);
|
||||
},
|
||||
.compressed, .treeless => {
|
||||
if (len > dest.buffer.len) return error.OutputBufferUndersize;
|
||||
const buf = try dest.writableSlice(len);
|
||||
const huffman_tree = self.huffman_tree.?;
|
||||
if (len > w.buffer.len) return error.OutputBufferUndersize;
|
||||
const buf = try w.writableSlice(len);
|
||||
const huffman_tree = d.huffman_tree.?;
|
||||
const max_bit_count = huffman_tree.max_bit_count;
|
||||
const starting_bit_count = LiteralsSection.HuffmanTree.weightToBitCount(
|
||||
huffman_tree.nodes[huffman_tree.symbol_count_minus_one].weight,
|
||||
@ -720,7 +721,7 @@ pub const Frame = struct {
|
||||
for (buf) |*out| {
|
||||
var prefix: u16 = 0;
|
||||
while (true) {
|
||||
const new_bits = try self.readLiteralsBits(bit_count_to_read);
|
||||
const new_bits = try d.readLiteralsBits(bit_count_to_read);
|
||||
prefix <<= bit_count_to_read;
|
||||
prefix |= new_bits;
|
||||
bits_read += bit_count_to_read;
|
||||
@ -750,7 +751,7 @@ pub const Frame = struct {
|
||||
}
|
||||
|
||||
/// TODO: don't use `@field`
|
||||
fn getCode(self: *Decode, comptime choice: DataType) u32 {
|
||||
fn getCode(self: *Decode, comptime choice: WhichFse) u32 {
|
||||
return switch (@field(self, @tagName(choice)).table) {
|
||||
.rle => |value| value,
|
||||
.fse => |table| table[@field(self, @tagName(choice)).state].symbol,
|
||||
@ -1166,7 +1167,7 @@ pub const LiteralsSection = struct {
|
||||
.raw => {
|
||||
if (buffer.len < header.regenerated_size) return error.MalformedLiteralsSection;
|
||||
remaining.* = remaining.subtract(header.regenerated_size) orelse return error.EndOfStream;
|
||||
try in.readSlice(buffer[0..header.regenerated_size]);
|
||||
try in.readSliceAll(buffer[0..header.regenerated_size]);
|
||||
return .{
|
||||
.header = header,
|
||||
.huffman_tree = null,
|
||||
@ -1193,7 +1194,7 @@ pub const LiteralsSection = struct {
|
||||
return error.MalformedLiteralsSection;
|
||||
if (total_streams_size > buffer.len) return error.MalformedLiteralsSection;
|
||||
remaining.* = remaining.subtract(total_streams_size) orelse return error.EndOfStream;
|
||||
try in.readSlice(buffer[0..total_streams_size]);
|
||||
try in.readSliceAll(buffer[0..total_streams_size]);
|
||||
const stream_data = buffer[0..total_streams_size];
|
||||
const streams = try Streams.decode(header.size_format, stream_data);
|
||||
return .{
|
||||
|
||||
@ -1809,7 +1809,19 @@ pub const Writer = struct {
|
||||
/// along with other write failures.
|
||||
pub fn end(w: *Writer) EndError!void {
|
||||
try w.interface.flush();
|
||||
return w.file.setEndPos(w.pos);
|
||||
switch (w.mode) {
|
||||
.positional,
|
||||
.positional_reading,
|
||||
=> w.file.setEndPos(w.pos) catch |err| switch (err) {
|
||||
error.NonResizable => return,
|
||||
else => |e| return e,
|
||||
},
|
||||
|
||||
.streaming,
|
||||
.streaming_reading,
|
||||
.failure,
|
||||
=> {},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1052,6 +1052,7 @@ pub const TruncateError = error{
|
||||
FileBusy,
|
||||
AccessDenied,
|
||||
PermissionDenied,
|
||||
NonResizable,
|
||||
} || UnexpectedError;
|
||||
|
||||
/// Length must be positive when treated as an i64.
|
||||
@ -1091,7 +1092,7 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
|
||||
.PERM => return error.PermissionDenied,
|
||||
.TXTBSY => return error.FileBusy,
|
||||
.BADF => unreachable, // Handle not open for writing
|
||||
.INVAL => unreachable, // Handle not open for writing, negative length, or non-resizable handle
|
||||
.INVAL => return error.NonResizable,
|
||||
.NOTCAPABLE => return error.AccessDenied,
|
||||
else => |err| return unexpectedErrno(err),
|
||||
}
|
||||
@ -1107,7 +1108,7 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
|
||||
.PERM => return error.PermissionDenied,
|
||||
.TXTBSY => return error.FileBusy,
|
||||
.BADF => unreachable, // Handle not open for writing
|
||||
.INVAL => unreachable, // Handle not open for writing, negative length, or non-resizable handle
|
||||
.INVAL => return error.NonResizable, // This is returned for /dev/null for example.
|
||||
else => |err| return unexpectedErrno(err),
|
||||
}
|
||||
}
|
||||
|
||||
@ -4880,6 +4880,14 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
|
||||
try seen_table.ensureUnusedCapacity(comp.gpa, deps.len);
|
||||
for (deps) |dep| seen_table.putAssumeCapacity(dep, dep.fully_qualified_name);
|
||||
}
|
||||
|
||||
tar_file_writer.end() catch |err| {
|
||||
return comp.lockAndSetMiscFailure(
|
||||
.docs_copy,
|
||||
"unable to write '{f}/sources.tar': {t}",
|
||||
.{ docs_path, err },
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
fn docsCopyModule(
|
||||
|
||||
@ -1198,7 +1198,8 @@ fn unpackResource(
|
||||
|
||||
switch (file_type) {
|
||||
.tar => {
|
||||
var adapter = resource.reader().adaptToNewApi();
|
||||
var adapter_buffer: [1024]u8 = undefined;
|
||||
var adapter = resource.reader().adaptToNewApi(&adapter_buffer);
|
||||
return unpackTarball(f, tmp_directory.handle, &adapter.new_interface);
|
||||
},
|
||||
.@"tar.gz" => {
|
||||
@ -1227,14 +1228,12 @@ fn unpackResource(
|
||||
.@"tar.zst" => {
|
||||
const window_size = std.compress.zstd.default_window_len;
|
||||
const window_buffer = try f.arena.allocator().create([window_size]u8);
|
||||
const reader = resource.reader();
|
||||
var br = std.io.bufferedReaderSize(std.crypto.tls.max_ciphertext_record_len, reader);
|
||||
var dcp = std.compress.zstd.decompressor(br.reader(), .{
|
||||
.window_buffer = window_buffer,
|
||||
var adapter_buffer: [std.crypto.tls.max_ciphertext_record_len]u8 = undefined;
|
||||
var adapter = resource.reader().adaptToNewApi(&adapter_buffer);
|
||||
var decompress: std.compress.zstd.Decompress = .init(&adapter.new_interface, window_buffer, .{
|
||||
.verify_checksum = false,
|
||||
});
|
||||
var adapter_buffer: [1024]u8 = undefined;
|
||||
var adapter = dcp.reader().adaptToNewApi(&adapter_buffer);
|
||||
return try unpackTarball(f, tmp_directory.handle, &adapter.new_interface);
|
||||
return try unpackTarball(f, tmp_directory.handle, &decompress.reader);
|
||||
},
|
||||
.git_pack => return unpackGitPack(f, tmp_directory.handle, &resource.git) catch |err| switch (err) {
|
||||
error.FetchFailed => return error.FetchFailed,
|
||||
|
||||
@ -113,9 +113,7 @@ pub fn generate(
|
||||
},
|
||||
.stack_slot => |stack_slot| {
|
||||
assert(stack_slot.base == .sp);
|
||||
passed_vi.setParent(&isel, .{
|
||||
.stack_slot = named_stack_args.withOffset(stack_slot.offset),
|
||||
});
|
||||
passed_vi.changeStackSlot(&isel, named_stack_args.withOffset(stack_slot.offset));
|
||||
},
|
||||
.address, .value, .constant => unreachable,
|
||||
}
|
||||
|
||||
@ -215,6 +215,7 @@ fn nextToken(as: *Assemble, buf: *[token_buf_len]u8, comptime opts: struct {
|
||||
|
||||
const SymbolSpec = union(enum) {
|
||||
reg: struct { format: aarch64.encoding.Register.Format, allow_sp: bool = false },
|
||||
systemreg,
|
||||
imm: struct {
|
||||
type: std.builtin.Type.Int,
|
||||
multiple_of: comptime_int = 1,
|
||||
@ -227,6 +228,7 @@ const SymbolSpec = union(enum) {
|
||||
fn Storage(comptime spec: SymbolSpec) type {
|
||||
return switch (spec) {
|
||||
.reg => aarch64.encoding.Register,
|
||||
.systemreg => aarch64.encoding.Register.System,
|
||||
.imm => |imm| @Type(.{ .int = imm.type }),
|
||||
.extend => Instruction.DataProcessingRegister.AddSubtractExtendedRegister.Option,
|
||||
.shift => Instruction.DataProcessingRegister.Shift.Op,
|
||||
@ -238,8 +240,7 @@ const SymbolSpec = union(enum) {
|
||||
const Result = Storage(spec);
|
||||
switch (spec) {
|
||||
.reg => |reg_spec| {
|
||||
var buf: [token_buf_len]u8 = undefined;
|
||||
const reg = Result.parse(std.ascii.lowerString(&buf, token[0..@min(token.len, buf.len)])) orelse {
|
||||
const reg = Result.parse(token) orelse {
|
||||
log.debug("invalid register: \"{f}\"", .{std.zig.fmtString(token)});
|
||||
return null;
|
||||
};
|
||||
@ -253,6 +254,14 @@ const SymbolSpec = union(enum) {
|
||||
}
|
||||
return reg;
|
||||
},
|
||||
.systemreg => {
|
||||
const systemreg = Result.parse(token) orelse {
|
||||
log.debug("invalid system register: \"{f}\"", .{std.zig.fmtString(token)});
|
||||
return null;
|
||||
};
|
||||
assert(systemreg.op0 >= 2);
|
||||
return systemreg;
|
||||
},
|
||||
.imm => |imm_spec| {
|
||||
const imm = std.fmt.parseInt(Result, token, 0) catch {
|
||||
log.debug("invalid immediate: \"{f}\"", .{std.zig.fmtString(token)});
|
||||
|
||||
@ -5535,7 +5535,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
|
||||
2 => if (elem_is_vector) .ldr(elem_ra.h(), .{ .extended_register = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.index = index_mat.ra.x(),
|
||||
.extend = .{ .lsl = 0 },
|
||||
.extend = .{ .lsl = 1 },
|
||||
} }) else switch (elem_vi.value.signedness(isel)) {
|
||||
.signed => .ldrsh(elem_ra.w(), .{ .extended_register = .{
|
||||
.base = base_mat.ra.x(),
|
||||
@ -5558,15 +5558,14 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
|
||||
.index = index_mat.ra.x(),
|
||||
.extend = .{ .lsl = 3 },
|
||||
} }),
|
||||
16 => .ldr(elem_ra.q(), .{ .extended_register = .{
|
||||
16 => if (elem_is_vector) .ldr(elem_ra.q(), .{ .extended_register = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.index = index_mat.ra.x(),
|
||||
.extend = .{ .lsl = 4 },
|
||||
} }),
|
||||
} }) else unreachable,
|
||||
});
|
||||
try index_mat.finish(isel);
|
||||
try base_mat.finish(isel);
|
||||
break :unused;
|
||||
} else {
|
||||
const elem_ptr_ra = try isel.allocIntReg();
|
||||
defer isel.freeReg(elem_ptr_ra);
|
||||
@ -5611,66 +5610,81 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
|
||||
const ptr_ty = isel.air.typeOf(bin_op.lhs, ip);
|
||||
const ptr_info = ptr_ty.ptrInfo(zcu);
|
||||
const elem_size = elem_vi.value.size(isel);
|
||||
switch (elem_size) {
|
||||
const elem_is_vector = elem_vi.value.isVector(isel);
|
||||
if (switch (elem_size) {
|
||||
0 => unreachable,
|
||||
1, 2, 4, 8 => {
|
||||
const elem_ra = try elem_vi.value.defReg(isel) orelse break :unused;
|
||||
const base_vi = try isel.use(bin_op.lhs);
|
||||
const index_vi = try isel.use(bin_op.rhs);
|
||||
const base_mat = try base_vi.matReg(isel);
|
||||
const index_mat = try index_vi.matReg(isel);
|
||||
try isel.emit(switch (elem_size) {
|
||||
else => unreachable,
|
||||
1 => switch (elem_vi.value.signedness(isel)) {
|
||||
.signed => .ldrsb(elem_ra.w(), .{ .extended_register = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.index = index_mat.ra.x(),
|
||||
.extend = .{ .lsl = 0 },
|
||||
} }),
|
||||
.unsigned => .ldrb(elem_ra.w(), .{ .extended_register = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.index = index_mat.ra.x(),
|
||||
.extend = .{ .lsl = 0 },
|
||||
} }),
|
||||
},
|
||||
2 => switch (elem_vi.value.signedness(isel)) {
|
||||
.signed => .ldrsh(elem_ra.w(), .{ .extended_register = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.index = index_mat.ra.x(),
|
||||
.extend = .{ .lsl = 1 },
|
||||
} }),
|
||||
.unsigned => .ldrh(elem_ra.w(), .{ .extended_register = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.index = index_mat.ra.x(),
|
||||
.extend = .{ .lsl = 1 },
|
||||
} }),
|
||||
},
|
||||
4 => .ldr(elem_ra.w(), .{ .extended_register = .{
|
||||
1, 2, 4, 8 => true,
|
||||
16 => elem_is_vector,
|
||||
else => false,
|
||||
}) {
|
||||
const elem_ra = try elem_vi.value.defReg(isel) orelse break :unused;
|
||||
const base_vi = try isel.use(bin_op.lhs);
|
||||
const index_vi = try isel.use(bin_op.rhs);
|
||||
const base_mat = try base_vi.matReg(isel);
|
||||
const index_mat = try index_vi.matReg(isel);
|
||||
try isel.emit(switch (elem_size) {
|
||||
else => unreachable,
|
||||
1 => if (elem_is_vector) .ldr(elem_ra.b(), .{ .extended_register = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.index = index_mat.ra.x(),
|
||||
.extend = .{ .lsl = 0 },
|
||||
} }) else switch (elem_vi.value.signedness(isel)) {
|
||||
.signed => .ldrsb(elem_ra.w(), .{ .extended_register = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.index = index_mat.ra.x(),
|
||||
.extend = .{ .lsl = 2 },
|
||||
.extend = .{ .lsl = 0 },
|
||||
} }),
|
||||
8 => .ldr(elem_ra.x(), .{ .extended_register = .{
|
||||
.unsigned => .ldrb(elem_ra.w(), .{ .extended_register = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.index = index_mat.ra.x(),
|
||||
.extend = .{ .lsl = 3 },
|
||||
.extend = .{ .lsl = 0 },
|
||||
} }),
|
||||
});
|
||||
try index_mat.finish(isel);
|
||||
try base_mat.finish(isel);
|
||||
},
|
||||
else => {
|
||||
const elem_ptr_ra = try isel.allocIntReg();
|
||||
defer isel.freeReg(elem_ptr_ra);
|
||||
if (!try elem_vi.value.load(isel, ptr_ty.elemType2(zcu), elem_ptr_ra, .{
|
||||
.@"volatile" = ptr_info.flags.is_volatile,
|
||||
})) break :unused;
|
||||
const base_vi = try isel.use(bin_op.lhs);
|
||||
const base_mat = try base_vi.matReg(isel);
|
||||
const index_vi = try isel.use(bin_op.rhs);
|
||||
try isel.elemPtr(elem_ptr_ra, base_mat.ra, .add, elem_size, index_vi);
|
||||
try base_mat.finish(isel);
|
||||
},
|
||||
},
|
||||
2 => if (elem_is_vector) .ldr(elem_ra.h(), .{ .extended_register = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.index = index_mat.ra.x(),
|
||||
.extend = .{ .lsl = 1 },
|
||||
} }) else switch (elem_vi.value.signedness(isel)) {
|
||||
.signed => .ldrsh(elem_ra.w(), .{ .extended_register = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.index = index_mat.ra.x(),
|
||||
.extend = .{ .lsl = 1 },
|
||||
} }),
|
||||
.unsigned => .ldrh(elem_ra.w(), .{ .extended_register = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.index = index_mat.ra.x(),
|
||||
.extend = .{ .lsl = 1 },
|
||||
} }),
|
||||
},
|
||||
4 => .ldr(if (elem_is_vector) elem_ra.s() else elem_ra.w(), .{ .extended_register = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.index = index_mat.ra.x(),
|
||||
.extend = .{ .lsl = 2 },
|
||||
} }),
|
||||
8 => .ldr(if (elem_is_vector) elem_ra.d() else elem_ra.x(), .{ .extended_register = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.index = index_mat.ra.x(),
|
||||
.extend = .{ .lsl = 3 },
|
||||
} }),
|
||||
16 => if (elem_is_vector) .ldr(elem_ra.q(), .{ .extended_register = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.index = index_mat.ra.x(),
|
||||
.extend = .{ .lsl = 4 },
|
||||
} }) else unreachable,
|
||||
});
|
||||
try index_mat.finish(isel);
|
||||
try base_mat.finish(isel);
|
||||
} else {
|
||||
const elem_ptr_ra = try isel.allocIntReg();
|
||||
defer isel.freeReg(elem_ptr_ra);
|
||||
if (!try elem_vi.value.load(isel, ptr_ty.elemType2(zcu), elem_ptr_ra, .{
|
||||
.@"volatile" = ptr_info.flags.is_volatile,
|
||||
})) break :unused;
|
||||
const base_vi = try isel.use(bin_op.lhs);
|
||||
const base_mat = try base_vi.matReg(isel);
|
||||
const index_vi = try isel.use(bin_op.rhs);
|
||||
try isel.elemPtr(elem_ptr_ra, base_mat.ra, .add, elem_size, index_vi);
|
||||
try base_mat.finish(isel);
|
||||
}
|
||||
}
|
||||
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
|
||||
@ -6250,11 +6264,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
|
||||
try agg_part_vi.?.move(isel, elems[field_index]);
|
||||
field_offset += field_size;
|
||||
}
|
||||
assert(field_offset == agg_vi.value.size(isel));
|
||||
assert(loaded_struct.flagsUnordered(ip).alignment.forward(field_offset) == agg_vi.value.size(isel));
|
||||
},
|
||||
.tuple_type => |tuple_type| {
|
||||
const elems: []const Air.Inst.Ref =
|
||||
@ptrCast(isel.air.extra.items[ty_pl.payload..][0..tuple_type.types.len]);
|
||||
var tuple_align: InternPool.Alignment = .@"1";
|
||||
var field_offset: u64 = 0;
|
||||
for (
|
||||
tuple_type.types.get(ip),
|
||||
@ -6263,7 +6278,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
|
||||
) |field_ty_index, field_val, elem| {
|
||||
if (field_val != .none) continue;
|
||||
const field_ty: ZigType = .fromInterned(field_ty_index);
|
||||
field_offset = field_ty.abiAlignment(zcu).forward(field_offset);
|
||||
const field_align = field_ty.abiAlignment(zcu);
|
||||
tuple_align = tuple_align.maxStrict(field_align);
|
||||
field_offset = field_align.forward(field_offset);
|
||||
const field_size = field_ty.abiSize(zcu);
|
||||
if (field_size == 0) continue;
|
||||
var agg_part_it = agg_vi.value.field(agg_ty, field_offset, field_size);
|
||||
@ -6271,7 +6288,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
|
||||
try agg_part_vi.?.move(isel, elem);
|
||||
field_offset += field_size;
|
||||
}
|
||||
assert(field_offset == agg_vi.value.size(isel));
|
||||
assert(tuple_align.forward(field_offset) == agg_vi.value.size(isel));
|
||||
},
|
||||
else => return isel.fail("aggregate init {f}", .{isel.fmtType(agg_ty)}),
|
||||
}
|
||||
@ -7283,6 +7300,175 @@ fn ctzLimb(
|
||||
}
|
||||
}
|
||||
|
||||
fn loadReg(
|
||||
isel: *Select,
|
||||
ra: Register.Alias,
|
||||
size: u64,
|
||||
signedness: std.builtin.Signedness,
|
||||
base_ra: Register.Alias,
|
||||
offset: i65,
|
||||
) !void {
|
||||
switch (size) {
|
||||
0 => unreachable,
|
||||
1 => {
|
||||
if (std.math.cast(u12, offset)) |unsigned_offset| return isel.emit(if (ra.isVector()) .ldr(
|
||||
ra.b(),
|
||||
.{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = unsigned_offset,
|
||||
} },
|
||||
) else switch (signedness) {
|
||||
.signed => .ldrsb(ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = unsigned_offset,
|
||||
} }),
|
||||
.unsigned => .ldrb(ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = unsigned_offset,
|
||||
} }),
|
||||
});
|
||||
if (std.math.cast(i9, offset)) |signed_offset| return isel.emit(if (ra.isVector())
|
||||
.ldur(ra.b(), base_ra.x(), signed_offset)
|
||||
else switch (signedness) {
|
||||
.signed => .ldursb(ra.w(), base_ra.x(), signed_offset),
|
||||
.unsigned => .ldurb(ra.w(), base_ra.x(), signed_offset),
|
||||
});
|
||||
},
|
||||
2 => {
|
||||
if (std.math.cast(u13, offset)) |unsigned_offset| if (unsigned_offset % 2 == 0)
|
||||
return isel.emit(if (ra.isVector()) .ldr(
|
||||
ra.h(),
|
||||
.{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = unsigned_offset,
|
||||
} },
|
||||
) else switch (signedness) {
|
||||
.signed => .ldrsh(
|
||||
ra.w(),
|
||||
.{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = unsigned_offset,
|
||||
} },
|
||||
),
|
||||
.unsigned => .ldrh(
|
||||
ra.w(),
|
||||
.{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = unsigned_offset,
|
||||
} },
|
||||
),
|
||||
});
|
||||
if (std.math.cast(i9, offset)) |signed_offset| return isel.emit(if (ra.isVector())
|
||||
.ldur(ra.h(), base_ra.x(), signed_offset)
|
||||
else switch (signedness) {
|
||||
.signed => .ldursh(ra.w(), base_ra.x(), signed_offset),
|
||||
.unsigned => .ldurh(ra.w(), base_ra.x(), signed_offset),
|
||||
});
|
||||
},
|
||||
3 => {
|
||||
const lo16_ra = try isel.allocIntReg();
|
||||
defer isel.freeReg(lo16_ra);
|
||||
try isel.emit(.orr(ra.w(), lo16_ra.w(), .{ .shifted_register = .{
|
||||
.register = ra.w(),
|
||||
.shift = .{ .lsl = 16 },
|
||||
} }));
|
||||
try isel.loadReg(ra, 1, signedness, base_ra, offset + 2);
|
||||
return isel.loadReg(lo16_ra, 2, .unsigned, base_ra, offset);
|
||||
},
|
||||
4 => {
|
||||
if (std.math.cast(u14, offset)) |unsigned_offset| if (unsigned_offset % 4 == 0) return isel.emit(.ldr(
|
||||
if (ra.isVector()) ra.s() else ra.w(),
|
||||
.{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = unsigned_offset,
|
||||
} },
|
||||
));
|
||||
if (std.math.cast(i9, offset)) |signed_offset| return isel.emit(.ldur(
|
||||
if (ra.isVector()) ra.s() else ra.w(),
|
||||
base_ra.x(),
|
||||
signed_offset,
|
||||
));
|
||||
},
|
||||
5, 6 => {
|
||||
const lo32_ra = try isel.allocIntReg();
|
||||
defer isel.freeReg(lo32_ra);
|
||||
try isel.emit(.orr(ra.x(), lo32_ra.x(), .{ .shifted_register = .{
|
||||
.register = ra.x(),
|
||||
.shift = .{ .lsl = 32 },
|
||||
} }));
|
||||
try isel.loadReg(ra, size - 4, signedness, base_ra, offset + 4);
|
||||
return isel.loadReg(lo32_ra, 4, .unsigned, base_ra, offset);
|
||||
},
|
||||
7 => {
|
||||
const lo32_ra = try isel.allocIntReg();
|
||||
defer isel.freeReg(lo32_ra);
|
||||
const lo48_ra = try isel.allocIntReg();
|
||||
defer isel.freeReg(lo48_ra);
|
||||
try isel.emit(.orr(ra.x(), lo48_ra.x(), .{ .shifted_register = .{
|
||||
.register = ra.x(),
|
||||
.shift = .{ .lsl = 32 + 16 },
|
||||
} }));
|
||||
try isel.loadReg(ra, 1, signedness, base_ra, offset + 4 + 2);
|
||||
try isel.emit(.orr(lo48_ra.x(), lo32_ra.x(), .{ .shifted_register = .{
|
||||
.register = lo48_ra.x(),
|
||||
.shift = .{ .lsl = 32 },
|
||||
} }));
|
||||
try isel.loadReg(lo48_ra, 2, .unsigned, base_ra, offset + 4);
|
||||
return isel.loadReg(lo32_ra, 4, .unsigned, base_ra, offset);
|
||||
},
|
||||
8 => {
|
||||
if (std.math.cast(u15, offset)) |unsigned_offset| if (unsigned_offset % 8 == 0) return isel.emit(.ldr(
|
||||
if (ra.isVector()) ra.d() else ra.x(),
|
||||
.{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = unsigned_offset,
|
||||
} },
|
||||
));
|
||||
if (std.math.cast(i9, offset)) |signed_offset| return isel.emit(.ldur(
|
||||
if (ra.isVector()) ra.d() else ra.x(),
|
||||
base_ra.x(),
|
||||
signed_offset,
|
||||
));
|
||||
},
|
||||
16 => {
|
||||
if (std.math.cast(u16, offset)) |unsigned_offset| if (unsigned_offset % 16 == 0) return isel.emit(.ldr(
|
||||
ra.q(),
|
||||
.{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = unsigned_offset,
|
||||
} },
|
||||
));
|
||||
if (std.math.cast(i9, offset)) |signed_offset| return isel.emit(.ldur(ra.q(), base_ra.x(), signed_offset));
|
||||
},
|
||||
else => return isel.fail("bad load size: {d}", .{size}),
|
||||
}
|
||||
const ptr_ra = try isel.allocIntReg();
|
||||
defer isel.freeReg(ptr_ra);
|
||||
try isel.loadReg(ra, size, signedness, ptr_ra, 0);
|
||||
if (std.math.cast(u24, offset)) |pos_offset| {
|
||||
const lo12: u12 = @truncate(pos_offset >> 0);
|
||||
const hi12: u12 = @intCast(pos_offset >> 12);
|
||||
if (hi12 > 0) try isel.emit(.add(
|
||||
ptr_ra.x(),
|
||||
if (lo12 > 0) ptr_ra.x() else base_ra.x(),
|
||||
.{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
|
||||
));
|
||||
if (lo12 > 0 or hi12 == 0) try isel.emit(.add(ptr_ra.x(), base_ra.x(), .{ .immediate = lo12 }));
|
||||
} else if (std.math.cast(u24, -offset)) |neg_offset| {
|
||||
const lo12: u12 = @truncate(neg_offset >> 0);
|
||||
const hi12: u12 = @intCast(neg_offset >> 12);
|
||||
if (hi12 > 0) try isel.emit(.sub(
|
||||
ptr_ra.x(),
|
||||
if (lo12 > 0) ptr_ra.x() else base_ra.x(),
|
||||
.{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
|
||||
));
|
||||
if (lo12 > 0 or hi12 == 0) try isel.emit(.sub(ptr_ra.x(), base_ra.x(), .{ .immediate = lo12 }));
|
||||
} else {
|
||||
try isel.emit(.add(ptr_ra.x(), base_ra.x(), .{ .register = ptr_ra.x() }));
|
||||
try isel.movImmediate(ptr_ra.x(), @truncate(@as(u65, @bitCast(offset))));
|
||||
}
|
||||
}
|
||||
|
||||
fn storeReg(
|
||||
isel: *Select,
|
||||
ra: Register.Alias,
|
||||
@ -7558,6 +7744,13 @@ pub const Value = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn changeStackSlot(vi: Value.Index, isel: *Select, new_stack_slot: Indirect) void {
|
||||
const value = vi.get(isel);
|
||||
assert(value.flags.parent_tag == .stack_slot);
|
||||
value.flags.parent_tag = .unallocated;
|
||||
vi.setParent(isel, .{ .stack_slot = new_stack_slot });
|
||||
}
|
||||
|
||||
pub fn parent(vi: Value.Index, isel: *Select) Parent {
|
||||
const value = vi.get(isel);
|
||||
return switch (value.flags.parent_tag) {
|
||||
@ -8070,123 +8263,7 @@ pub const Value = struct {
|
||||
}),
|
||||
64 => {},
|
||||
};
|
||||
try isel.emit(emit: switch (part_size) {
|
||||
else => return isel.fail("bad load size of {d}", .{part_size}),
|
||||
1 => if (part_is_vector) .ldr(part_ra.b(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset),
|
||||
} }) else switch (part_vi.signedness(isel)) {
|
||||
.signed => .ldrsb(part_ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset),
|
||||
} }),
|
||||
.unsigned => .ldrb(part_ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset),
|
||||
} }),
|
||||
},
|
||||
2 => if (part_is_vector) .ldr(part_ra.h(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset),
|
||||
} }) else switch (part_vi.signedness(isel)) {
|
||||
.signed => .ldrsh(part_ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset),
|
||||
} }),
|
||||
.unsigned => .ldrh(part_ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset),
|
||||
} }),
|
||||
},
|
||||
3 => {
|
||||
const lo16_ra = try isel.allocIntReg();
|
||||
defer isel.freeReg(lo16_ra);
|
||||
try isel.emit(.orr(part_ra.w(), lo16_ra.w(), .{ .shifted_register = .{
|
||||
.register = part_ra.w(),
|
||||
.shift = .{ .lsl = 16 },
|
||||
} }));
|
||||
try isel.emit(switch (part_vi.signedness(isel)) {
|
||||
.signed => .ldrsb(part_ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset + 2),
|
||||
} }),
|
||||
.unsigned => .ldrb(part_ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset + 2),
|
||||
} }),
|
||||
});
|
||||
break :emit .ldrh(lo16_ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset),
|
||||
} });
|
||||
},
|
||||
4 => .ldr(if (part_is_vector) part_ra.s() else part_ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset),
|
||||
} }),
|
||||
5 => {
|
||||
const lo32_ra = try isel.allocIntReg();
|
||||
defer isel.freeReg(lo32_ra);
|
||||
try isel.emit(.orr(part_ra.x(), lo32_ra.x(), .{ .shifted_register = .{
|
||||
.register = part_ra.x(),
|
||||
.shift = .{ .lsl = 32 },
|
||||
} }));
|
||||
try isel.emit(switch (part_vi.signedness(isel)) {
|
||||
.signed => .ldrsb(part_ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset + 4),
|
||||
} }),
|
||||
.unsigned => .ldrb(part_ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset + 4),
|
||||
} }),
|
||||
});
|
||||
break :emit .ldr(lo32_ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset),
|
||||
} });
|
||||
},
|
||||
7 => {
|
||||
const lo32_ra = try isel.allocIntReg();
|
||||
defer isel.freeReg(lo32_ra);
|
||||
const lo48_ra = try isel.allocIntReg();
|
||||
defer isel.freeReg(lo48_ra);
|
||||
try isel.emit(.orr(part_ra.x(), lo48_ra.x(), .{ .shifted_register = .{
|
||||
.register = part_ra.x(),
|
||||
.shift = .{ .lsl = 32 + 16 },
|
||||
} }));
|
||||
try isel.emit(switch (part_vi.signedness(isel)) {
|
||||
.signed => .ldrsb(part_ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset + 4 + 2),
|
||||
} }),
|
||||
.unsigned => .ldrb(part_ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset + 4 + 2),
|
||||
} }),
|
||||
});
|
||||
try isel.emit(.orr(lo48_ra.x(), lo32_ra.x(), .{ .shifted_register = .{
|
||||
.register = lo48_ra.x(),
|
||||
.shift = .{ .lsl = 32 },
|
||||
} }));
|
||||
try isel.emit(.ldrh(lo48_ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset + 4),
|
||||
} }));
|
||||
break :emit .ldr(lo32_ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset),
|
||||
} });
|
||||
},
|
||||
8 => .ldr(if (part_is_vector) part_ra.d() else part_ra.x(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset),
|
||||
} }),
|
||||
16 => .ldr(part_ra.q(), .{ .unsigned_offset = .{
|
||||
.base = base_ra.x(),
|
||||
.offset = @intCast(opts.offset),
|
||||
} }),
|
||||
});
|
||||
try isel.loadReg(part_ra, part_size, part_vi.signedness(isel), base_ra, opts.offset);
|
||||
if (part_ra != .zr) {
|
||||
const live_vi = isel.live_registers.getPtr(part_ra);
|
||||
assert(live_vi.* == .allocating);
|
||||
@ -9104,7 +9181,7 @@ pub const Value = struct {
|
||||
const live_vi = isel.live_registers.getPtr(mat.ra);
|
||||
assert(live_vi.* == .allocating);
|
||||
var vi = mat.vi;
|
||||
var offset: i65 = 0;
|
||||
var offset: u64 = 0;
|
||||
const size = mat.vi.size(isel);
|
||||
free: while (true) {
|
||||
if (vi.register(isel)) |ra| {
|
||||
@ -9156,93 +9233,16 @@ pub const Value = struct {
|
||||
live_vi.* = mat.vi;
|
||||
return;
|
||||
},
|
||||
.stack_slot => |stack_slot| {
|
||||
offset += stack_slot.offset;
|
||||
break :free try isel.emit(switch (size) {
|
||||
else => unreachable,
|
||||
1 => if (mat.ra.isVector()) .ldr(mat.ra.b(), .{ .unsigned_offset = .{
|
||||
.base = stack_slot.base.x(),
|
||||
.offset = @intCast(offset),
|
||||
} }) else switch (mat.vi.signedness(isel)) {
|
||||
.signed => .ldrsb(mat.ra.w(), .{ .unsigned_offset = .{
|
||||
.base = stack_slot.base.x(),
|
||||
.offset = @intCast(offset),
|
||||
} }),
|
||||
.unsigned => .ldrb(mat.ra.w(), .{ .unsigned_offset = .{
|
||||
.base = stack_slot.base.x(),
|
||||
.offset = @intCast(offset),
|
||||
} }),
|
||||
},
|
||||
2 => if (mat.ra.isVector()) .ldr(mat.ra.h(), .{ .unsigned_offset = .{
|
||||
.base = stack_slot.base.x(),
|
||||
.offset = @intCast(offset),
|
||||
} }) else switch (mat.vi.signedness(isel)) {
|
||||
.signed => .ldrsh(mat.ra.w(), .{ .unsigned_offset = .{
|
||||
.base = stack_slot.base.x(),
|
||||
.offset = @intCast(offset),
|
||||
} }),
|
||||
.unsigned => .ldrh(mat.ra.w(), .{ .unsigned_offset = .{
|
||||
.base = stack_slot.base.x(),
|
||||
.offset = @intCast(offset),
|
||||
} }),
|
||||
},
|
||||
4 => .ldr(if (mat.ra.isVector()) mat.ra.s() else mat.ra.w(), .{ .unsigned_offset = .{
|
||||
.base = stack_slot.base.x(),
|
||||
.offset = @intCast(offset),
|
||||
} }),
|
||||
8 => .ldr(if (mat.ra.isVector()) mat.ra.d() else mat.ra.x(), .{ .unsigned_offset = .{
|
||||
.base = stack_slot.base.x(),
|
||||
.offset = @intCast(offset),
|
||||
} }),
|
||||
16 => .ldr(mat.ra.q(), .{ .unsigned_offset = .{
|
||||
.base = stack_slot.base.x(),
|
||||
.offset = @intCast(offset),
|
||||
} }),
|
||||
});
|
||||
},
|
||||
.stack_slot => |stack_slot| break :free try isel.loadReg(
|
||||
mat.ra,
|
||||
size,
|
||||
mat.vi.signedness(isel),
|
||||
stack_slot.base,
|
||||
@as(i65, stack_slot.offset) + offset,
|
||||
),
|
||||
.address => |base_vi| {
|
||||
const base_mat = try base_vi.matReg(isel);
|
||||
try isel.emit(switch (size) {
|
||||
else => unreachable,
|
||||
1 => if (mat.ra.isVector()) .ldr(mat.ra.b(), .{ .unsigned_offset = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.offset = @intCast(offset),
|
||||
} }) else switch (mat.vi.signedness(isel)) {
|
||||
.signed => .ldrsb(mat.ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.offset = @intCast(offset),
|
||||
} }),
|
||||
.unsigned => .ldrb(mat.ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.offset = @intCast(offset),
|
||||
} }),
|
||||
},
|
||||
2 => if (mat.ra.isVector()) .ldr(mat.ra.h(), .{ .unsigned_offset = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.offset = @intCast(offset),
|
||||
} }) else switch (mat.vi.signedness(isel)) {
|
||||
.signed => .ldrsh(mat.ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.offset = @intCast(offset),
|
||||
} }),
|
||||
.unsigned => .ldrh(mat.ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.offset = @intCast(offset),
|
||||
} }),
|
||||
},
|
||||
4 => .ldr(if (mat.ra.isVector()) mat.ra.s() else mat.ra.w(), .{ .unsigned_offset = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.offset = @intCast(offset),
|
||||
} }),
|
||||
8 => .ldr(if (mat.ra.isVector()) mat.ra.d() else mat.ra.x(), .{ .unsigned_offset = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.offset = @intCast(offset),
|
||||
} }),
|
||||
16 => .ldr(mat.ra.q(), .{ .unsigned_offset = .{
|
||||
.base = base_mat.ra.x(),
|
||||
.offset = @intCast(offset),
|
||||
} }),
|
||||
});
|
||||
try isel.loadReg(mat.ra, size, mat.vi.signedness(isel), base_mat.ra, offset);
|
||||
break :free try base_mat.finish(isel);
|
||||
},
|
||||
.value => |parent_vi| vi = parent_vi,
|
||||
|
||||
@ -1072,7 +1072,7 @@ pub const Register = struct {
|
||||
}
|
||||
|
||||
pub fn parse(reg: []const u8) ?Register {
|
||||
return if (reg.len == 0) null else switch (reg[0]) {
|
||||
return if (reg.len == 0) null else switch (std.ascii.toLower(reg[0])) {
|
||||
else => null,
|
||||
'r' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| switch (n) {
|
||||
0...30 => .{
|
||||
@ -1087,27 +1087,27 @@ pub const Register = struct {
|
||||
.format = .{ .integer = .doubleword },
|
||||
},
|
||||
31 => null,
|
||||
} else |_| if (std.mem.eql(u8, reg, "xzr")) .xzr else null,
|
||||
} else |_| if (toLowerEqlAssertLower(reg, "xzr")) .xzr else null,
|
||||
'w' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| switch (n) {
|
||||
0...30 => .{
|
||||
.alias = @enumFromInt(@intFromEnum(Alias.r0) + n),
|
||||
.format = .{ .integer = .word },
|
||||
},
|
||||
31 => null,
|
||||
} else |_| if (std.mem.eql(u8, reg, "wzr"))
|
||||
} else |_| if (toLowerEqlAssertLower(reg, "wzr"))
|
||||
.wzr
|
||||
else if (std.mem.eql(u8, reg, "wsp"))
|
||||
else if (toLowerEqlAssertLower(reg, "wsp"))
|
||||
.wsp
|
||||
else
|
||||
null,
|
||||
'i' => return if (std.mem.eql(u8, reg, "ip") or std.mem.eql(u8, reg, "ip0"))
|
||||
'i' => return if (toLowerEqlAssertLower(reg, "ip") or toLowerEqlAssertLower(reg, "ip0"))
|
||||
.ip0
|
||||
else if (std.mem.eql(u8, reg, "ip1"))
|
||||
else if (toLowerEqlAssertLower(reg, "ip1"))
|
||||
.ip1
|
||||
else
|
||||
null,
|
||||
'f' => return if (std.mem.eql(u8, reg, "fp")) .fp else null,
|
||||
'p' => return if (std.mem.eql(u8, reg, "pc")) .pc else null,
|
||||
'f' => return if (toLowerEqlAssertLower(reg, "fp")) .fp else null,
|
||||
'p' => return if (toLowerEqlAssertLower(reg, "pc")) .pc else null,
|
||||
'v' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{
|
||||
.alias = @enumFromInt(@intFromEnum(Alias.v0) + n),
|
||||
.format = .alias,
|
||||
@ -1123,7 +1123,7 @@ pub const Register = struct {
|
||||
's' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{
|
||||
.alias = @enumFromInt(@intFromEnum(Alias.v0) + n),
|
||||
.format = .{ .scalar = .single },
|
||||
} else |_| if (std.mem.eql(u8, reg, "sp")) .sp else null,
|
||||
} else |_| if (toLowerEqlAssertLower(reg, "sp")) .sp else null,
|
||||
'h' => if (std.fmt.parseInt(u5, reg[1..], 10)) |n| .{
|
||||
.alias = @enumFromInt(@intFromEnum(Alias.v0) + n),
|
||||
.format = .{ .scalar = .half },
|
||||
@ -1141,6 +1141,422 @@ pub const Register = struct {
|
||||
pub fn fmtCase(reg: Register, case: aarch64.Disassemble.Case) aarch64.Disassemble.RegisterFormatter {
|
||||
return .{ .reg = reg, .case = case };
|
||||
}
|
||||
|
||||
pub const System = packed struct(u16) {
|
||||
op2: u3,
|
||||
CRm: u4,
|
||||
CRn: u4,
|
||||
op1: u3,
|
||||
op0: u2,
|
||||
|
||||
// D19.2 General system control registers
|
||||
/// D19.2.1 ACCDATA_EL1, Accelerator Data
|
||||
pub const accdata_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b101 };
|
||||
/// D19.2.2 ACTLR_EL1, Auxiliary Control Register (EL1)
|
||||
pub const actlr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b001 };
|
||||
/// D19.2.3 ACTLR_EL2, Auxiliary Control Register (EL2)
|
||||
pub const actlr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b001 };
|
||||
/// D19.2.4 ACTLR_EL3, Auxiliary Control Register (EL3)
|
||||
pub const actlr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b001 };
|
||||
/// D19.2.5 AFSR0_EL1, Auxiliary Fault Status Register 0 (EL1)
|
||||
pub const afsr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b000 };
|
||||
/// D19.2.5 AFSR0_EL12, Auxiliary Fault Status Register 0 (EL12)
|
||||
pub const afsr0_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b000 };
|
||||
/// D19.2.6 AFSR0_EL2, Auxiliary Fault Status Register 0 (EL2)
|
||||
pub const afsr0_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b000 };
|
||||
/// D19.2.7 AFSR0_EL3, Auxiliary Fault Status Register 0 (EL3)
|
||||
pub const afsr0_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b000 };
|
||||
/// D19.2.8 AFSR1_EL1, Auxiliary Fault Status Register 1 (EL1)
|
||||
pub const afsr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b001 };
|
||||
/// D19.2.8 AFSR1_EL12, Auxiliary Fault Status Register 1 (EL12)
|
||||
pub const afsr1_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b001 };
|
||||
/// D19.2.9 AFSR1_EL2, Auxiliary Fault Status Register 1 (EL2)
|
||||
pub const afsr1_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b001 };
|
||||
/// D19.2.10 AFSR1_EL3, Auxiliary Fault Status Register 1 (EL3)
|
||||
pub const afsr1_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0101, .CRm = 0b0001, .op2 = 0b001 };
|
||||
/// D19.2.11 AIDR_EL1, Auxiliary ID Register
|
||||
pub const aidr_el1: System = .{ .op0 = 0b11, .op1 = 0b001, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b111 };
|
||||
/// D19.2.12 AMAIR_EL1, Auxiliary Memory Attribute Indirection Register (EL1)
|
||||
pub const amair_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0011, .op2 = 0b000 };
|
||||
/// D19.2.12 AMAIR_EL12, Auxiliary Memory Attribute Indirection Register (EL12)
|
||||
pub const amair_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b1010, .CRm = 0b0011, .op2 = 0b000 };
|
||||
/// D19.2.13 AMAIR_EL2, Auxiliary Memory Attribute Indirection Register (EL2)
|
||||
pub const amair_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1010, .CRm = 0b0011, .op2 = 0b000 };
|
||||
/// D19.2.14 AMAIR_EL3, Auxiliary Memory Attribute Indirection Register (EL3)
|
||||
pub const amair_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1010, .CRm = 0b0011, .op2 = 0b000 };
|
||||
/// D19.2.15 APDAKeyHi_EL1, Pointer Authentication Key A for Data (bits[127:64])
|
||||
pub const apdakeyhi_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0010, .op2 = 0b001 };
|
||||
/// D19.2.16 APDAKeyLo_EL1, Pointer Authentication Key A for Data (bits[63:0])
|
||||
pub const apdakeylo_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0010, .op2 = 0b000 };
|
||||
/// D19.2.17 APDBKeyHi_EL1, Pointer Authentication Key B for Data (bits[127:64])
|
||||
pub const apdbkeyhi_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0010, .op2 = 0b011 };
|
||||
/// D19.2.18 APDAKeyHi_EL1, Pointer Authentication Key B for Data (bits[63:0])
|
||||
pub const apdbkeylo_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0010, .op2 = 0b010 };
|
||||
/// D19.2.19 APGAKeyHi_EL1, Pointer Authentication Key A for Code (bits[127:64])
|
||||
pub const apgakeyhi_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0011, .op2 = 0b001 };
|
||||
/// D19.2.20 APGAKeyLo_EL1, Pointer Authentication Key A for Code (bits[63:0])
|
||||
pub const apgakeylo_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0011, .op2 = 0b000 };
|
||||
/// D19.2.21 APIAKeyHi_EL1, Pointer Authentication Key A for Instruction (bits[127:64])
|
||||
pub const apiakeyhi_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0001, .op2 = 0b001 };
|
||||
/// D19.2.22 APIAKeyLo_EL1, Pointer Authentication Key A for Instruction (bits[63:0])
|
||||
pub const apiakeylo_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0001, .op2 = 0b000 };
|
||||
/// D19.2.23 APIBKeyHi_EL1, Pointer Authentication Key B for Instruction (bits[127:64])
|
||||
pub const apibkeyhi_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0001, .op2 = 0b011 };
|
||||
/// D19.2.24 APIBKeyLo_EL1, Pointer Authentication Key B for Instruction (bits[63:0])
|
||||
pub const apibkeylo_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0001, .op2 = 0b010 };
|
||||
/// D19.2.25 CCSIDR2_EL1, Current Cache Size ID Register 2
|
||||
pub const ccsidr2_el1: System = .{ .op0 = 0b11, .op1 = 0b001, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b010 };
|
||||
/// D19.2.26 CCSIDR_EL1, Current Cache Size ID Register
|
||||
pub const ccsidr_el1: System = .{ .op0 = 0b11, .op1 = 0b001, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.27 CLIDR_EL1, Cache Level ID Register
|
||||
pub const clidr_el1: System = .{ .op0 = 0b11, .op1 = 0b001, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b001 };
|
||||
/// D19.2.28 CONTEXTIDR_EL1, Context ID Register (EL1)
|
||||
pub const contextidr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b001 };
|
||||
/// D19.2.28 CONTEXTIDR_EL12, Context ID Register (EL12)
|
||||
pub const contextidr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b001 };
|
||||
/// D19.2.29 CONTEXTIDR_EL2, Context ID Register (EL2)
|
||||
pub const contextidr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b001 };
|
||||
/// D19.2.30 CPACR_EL1, Architectural Feature Access Control Register
|
||||
pub const cpacr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b010 };
|
||||
/// D19.2.30 CPACR_EL12, Architectural Feature Access Control Register
|
||||
pub const cpacr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b010 };
|
||||
/// D19.2.31 CPACR_EL2, Architectural Feature Trap Register (EL2)
|
||||
pub const cptr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b010 };
|
||||
/// D19.2.32 CPACR_EL3, Architectural Feature Trap Register (EL3)
|
||||
pub const cptr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b010 };
|
||||
/// D19.2.33 CSSELR_EL1, Cache Size Selection Register
|
||||
pub const csselr_el1: System = .{ .op0 = 0b11, .op1 = 0b010, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.34 CTR_EL0, Cache Type Register
|
||||
pub const ctr_el0: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b001 };
|
||||
/// D19.2.35 DACR32_EL2, Domain Access Control Register
|
||||
pub const dacr32_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0011, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.36 DCZID_EL0, Data Cache Zero ID Register
|
||||
pub const dczid_el0: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b111 };
|
||||
/// D19.2.37 ESR_EL1, Exception Syndrome Register (EL1)
|
||||
pub const esr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0101, .CRm = 0b0010, .op2 = 0b000 };
|
||||
/// D19.2.37 ESR_EL12, Exception Syndrome Register (EL12)
|
||||
pub const esr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0101, .CRm = 0b0010, .op2 = 0b000 };
|
||||
/// D19.2.38 ESR_EL2, Exception Syndrome Register (EL2)
|
||||
pub const esr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0101, .CRm = 0b0010, .op2 = 0b000 };
|
||||
/// D19.2.39 ESR_EL3, Exception Syndrome Register (EL3)
|
||||
pub const esr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0101, .CRm = 0b0010, .op2 = 0b000 };
|
||||
/// D19.2.40 FAR_EL1, Fault Address Register (EL1)
|
||||
pub const far_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0110, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.40 FAR_EL12, Fault Address Register (EL12)
|
||||
pub const far_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0110, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.41 FAR_EL2, Fault Address Register (EL2)
|
||||
pub const far_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0110, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.42 FAR_EL3, Fault Address Register (EL3)
|
||||
pub const far_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0110, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.43 FPEXC32_EL2, Floating-Point Exception Control Register
|
||||
pub const fpexc32_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0101, .CRm = 0b0011, .op2 = 0b000 };
|
||||
/// D19.2.44 GCR_EL1, Tag Control Register
|
||||
pub const gcr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b110 };
|
||||
/// D19.2.45 GMID_EL1, Tag Control Register
|
||||
pub const gmid_el1: System = .{ .op0 = 0b11, .op1 = 0b001, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b100 };
|
||||
/// D19.2.46 HACR_EL2, Hypervisor Auxiliary Control Register
|
||||
pub const hacr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b111 };
|
||||
/// D19.2.47 HAFGRTR_EL2, Hypervisor Activity Monitors Fine-Grained Read Trap Register
|
||||
pub const hafgrtr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0011, .CRm = 0b0001, .op2 = 0b110 };
|
||||
/// D19.2.48 HCR_EL2, Hypervisor Configuration Register
|
||||
pub const hcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b000 };
|
||||
/// D19.2.49 HCRX_EL2, Extended Hypervisor Configuration Register
|
||||
pub const hcrx_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b010 };
|
||||
/// D19.2.50 HDFGRTR_EL2, Hypervisor Debug Fine-Grained Read Trap Register
|
||||
pub const hdfgrtr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0011, .CRm = 0b0001, .op2 = 0b100 };
|
||||
/// D19.2.51 HDFGWTR_EL2, Hypervisor Debug Fine-Grained Write Trap Register
|
||||
pub const hdfgwtr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0011, .CRm = 0b0001, .op2 = 0b101 };
|
||||
/// D19.2.52 HFGITR_EL2, Hypervisor Fine-Grained Instruction Trap Register
|
||||
pub const hfgitr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b110 };
|
||||
/// D19.2.53 HFGRTR_EL2, Hypervisor Fine-Grained Read Trap Register
|
||||
pub const hfgrtr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b100 };
|
||||
/// D19.2.54 HFGWTR_EL2, Hypervisor Fine-Grained Write Trap Register
|
||||
pub const hfgwtr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b101 };
|
||||
/// D19.2.55 HPFAR_EL2, Hypervisor IPA Fault Address Register
|
||||
pub const hpfar_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0110, .CRm = 0b0000, .op2 = 0b100 };
|
||||
/// D19.2.56 HSTR_EL2, Hypervisor System Trap Register
|
||||
pub const hstr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b011 };
|
||||
/// D19.2.57 ID_AA64AFR0_EL1, AArch64 Auxiliary Feature Register 0
|
||||
pub const id_aa64afr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0101, .op2 = 0b100 };
|
||||
/// D19.2.58 ID_AA64AFR1_EL1, AArch64 Auxiliary Feature Register 1
|
||||
pub const id_aa64afr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0101, .op2 = 0b101 };
|
||||
/// D19.2.59 ID_AA64DFR0_EL1, AArch64 Debug Feature Register 0
|
||||
pub const id_aa64dfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0101, .op2 = 0b000 };
|
||||
/// D19.2.60 ID_AA64DFR1_EL1, AArch64 Debug Feature Register 1
|
||||
pub const id_aa64dfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0101, .op2 = 0b001 };
|
||||
/// D19.2.61 ID_AA64ISAR0_EL1, AArch64 Instruction Set Attribute Register 0
|
||||
pub const id_aa64isar0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0110, .op2 = 0b000 };
|
||||
/// D19.2.62 ID_AA64ISAR1_EL1, AArch64 Instruction Set Attribute Register 1
|
||||
pub const id_aa64isar1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0110, .op2 = 0b001 };
|
||||
/// D19.2.63 ID_AA64ISAR2_EL1, AArch64 Instruction Set Attribute Register 2
|
||||
pub const id_aa64isar2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0110, .op2 = 0b010 };
|
||||
/// D19.2.64 ID_AA64MMFR0_EL1, AArch64 Memory Model Feature Register 0
|
||||
pub const id_aa64mmfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0111, .op2 = 0b000 };
|
||||
/// D19.2.65 ID_AA64MMFR1_EL1, AArch64 Memory Model Feature Register 1
|
||||
pub const id_aa64mmfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0111, .op2 = 0b001 };
|
||||
/// D19.2.66 ID_AA64MMFR2_EL1, AArch64 Memory Model Feature Register 2
|
||||
pub const id_aa64mmfr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0111, .op2 = 0b010 };
|
||||
/// D19.2.67 ID_AA64MMFR3_EL1, AArch64 Memory Model Feature Register 3
|
||||
pub const id_aa64mmfr3_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0111, .op2 = 0b011 };
|
||||
/// D19.2.68 ID_AA64MMFR4_EL1, AArch64 Memory Model Feature Register 4
|
||||
pub const id_aa64mmfr4_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0111, .op2 = 0b100 };
|
||||
/// D19.2.69 ID_AA64PFR0_EL1, AArch64 Processor Feature Register 0
|
||||
pub const id_aa64pfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0100, .op2 = 0b000 };
|
||||
/// D19.2.70 ID_AA64PFR1_EL1, AArch64 Processor Feature Register 1
|
||||
pub const id_aa64pfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0100, .op2 = 0b001 };
|
||||
/// D19.2.71 ID_AA64PFR2_EL1, AArch64 Processor Feature Register 2
|
||||
pub const id_aa64pfr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0100, .op2 = 0b010 };
|
||||
/// D19.2.72 ID_AA64SMFR0_EL1, SME Feature ID Register 0
|
||||
pub const id_aa64smfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0100, .op2 = 0b101 };
|
||||
/// D19.2.73 ID_AA64ZFR0_EL1, SVE Feature ID Register 0
|
||||
pub const id_aa64zfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0100, .op2 = 0b100 };
|
||||
/// D19.2.74 ID_AFR0_EL1, AArch32 Auxiliary Feature Register 0
|
||||
pub const id_afr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b011 };
|
||||
/// D19.2.75 ID_DFR0_EL1, AArch32 Debug Feature Register 0
|
||||
pub const id_dfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b010 };
|
||||
/// D19.2.76 ID_DFR1_EL1, AArch32 Debug Feature Register 1
|
||||
pub const id_dfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0011, .op2 = 0b101 };
|
||||
/// D19.2.77 ID_ISAR0_EL1, AArch32 Instruction Set Attribute Register 0
|
||||
pub const id_isar0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b000 };
|
||||
/// D19.2.78 ID_ISAR1_EL1, AArch32 Instruction Set Attribute Register 1
|
||||
pub const id_isar1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b001 };
|
||||
/// D19.2.79 ID_ISAR2_EL1, AArch32 Instruction Set Attribute Register 2
|
||||
pub const id_isar2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b010 };
|
||||
/// D19.2.80 ID_ISAR3_EL1, AArch32 Instruction Set Attribute Register 3
|
||||
pub const id_isar3_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b011 };
|
||||
/// D19.2.81 ID_ISAR4_EL1, AArch32 Instruction Set Attribute Register 4
|
||||
pub const id_isar4_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b100 };
|
||||
/// D19.2.82 ID_ISAR5_EL1, AArch32 Instruction Set Attribute Register 5
|
||||
pub const id_isar5_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b101 };
|
||||
/// D19.2.83 ID_ISAR6_EL1, AArch32 Instruction Set Attribute Register 6
|
||||
pub const id_isar6_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b111 };
|
||||
/// D19.2.84 ID_MMFR0_EL1, AArch32 Memory Model Feature Register 0
|
||||
pub const id_mmfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b100 };
|
||||
/// D19.2.85 ID_MMFR1_EL1, AArch32 Memory Model Feature Register 1
|
||||
pub const id_mmfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b101 };
|
||||
/// D19.2.86 ID_MMFR2_EL1, AArch32 Memory Model Feature Register 2
|
||||
pub const id_mmfr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b110 };
|
||||
/// D19.2.87 ID_MMFR3_EL1, AArch32 Memory Model Feature Register 3
|
||||
pub const id_mmfr3_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b111 };
|
||||
/// D19.2.88 ID_MMFR4_EL1, AArch32 Memory Model Feature Register 4
|
||||
pub const id_mmfr4_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0010, .op2 = 0b110 };
|
||||
/// D19.2.89 ID_MMFR5_EL1, AArch32 Memory Model Feature Register 5
|
||||
pub const id_mmfr5_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0011, .op2 = 0b110 };
|
||||
/// D19.2.90 ID_PFR0_EL1, AArch32 Processor Feature Register 0
|
||||
pub const id_pfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b000 };
|
||||
/// D19.2.91 ID_PFR1_EL1, AArch32 Processor Feature Register 1
|
||||
pub const id_pfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0001, .op2 = 0b001 };
|
||||
/// D19.2.92 ID_PFR2_EL1, AArch32 Processor Feature Register 2
|
||||
pub const id_pfr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0011, .op2 = 0b100 };
|
||||
/// D19.2.93 IFSR32_EL2, Instruction Fault Status Register (EL2)
|
||||
pub const ifsr32_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0101, .CRm = 0b0000, .op2 = 0b001 };
|
||||
/// D19.2.94 ISR_EL1, Interrupt Status Register
|
||||
pub const isr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1100, .CRm = 0b0001, .op2 = 0b000 };
|
||||
/// D19.2.95 LORC_EL1, LORegion Control (EL1)
|
||||
pub const lorc_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0100, .op2 = 0b011 };
|
||||
/// D19.2.96 LOREA_EL1, LORegion End Address (EL1)
|
||||
pub const lorea_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0100, .op2 = 0b001 };
|
||||
/// D19.2.97 SORID_EL1, LORegionID (EL1)
|
||||
pub const lorid_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0100, .op2 = 0b111 };
|
||||
/// D19.2.98 LORN_EL1, LORegion Number (EL1)
|
||||
pub const lorn_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0100, .op2 = 0b010 };
|
||||
/// D19.2.99 LORSA_EL1, LORegion Start Address (EL1)
|
||||
pub const lorsa_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0100, .op2 = 0b000 };
|
||||
/// D19.2.100 MAIR_EL1, Memory Attribute Indirection Register (EL1)
|
||||
pub const mair_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1010, .CRm = 0b0010, .op2 = 0b000 };
|
||||
/// D19.2.100 MAIR_EL12, Memory Attribute Indirection Register (EL12)
|
||||
pub const mair_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b1010, .CRm = 0b0010, .op2 = 0b000 };
|
||||
/// D19.2.101 MAIR_EL2, Memory Attribute Indirection Register (EL2)
|
||||
pub const mair_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1010, .CRm = 0b0010, .op2 = 0b000 };
|
||||
/// D19.2.102 MAIR_EL3, Memory Attribute Indirection Register (EL3)
|
||||
pub const mair_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1010, .CRm = 0b0010, .op2 = 0b000 };
|
||||
/// D19.2.103 MIDR_EL1, Main ID Register
|
||||
pub const midr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.104 MPIDR_EL1, Multiprocessor Affinity Register
|
||||
pub const mpidr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b101 };
|
||||
/// D19.2.105 MVFR0_EL1, AArch32 Media and VFP Feature Register 0
|
||||
pub const mvfr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0011, .op2 = 0b000 };
|
||||
/// D19.2.106 MVFR1_EL1, AArch32 Media and VFP Feature Register 1
|
||||
pub const mvfr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0011, .op2 = 0b001 };
|
||||
/// D19.2.107 MVFR2_EL1, AArch32 Media and VFP Feature Register 2
|
||||
pub const mvfr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0011, .op2 = 0b010 };
|
||||
/// D19.2.108 PAR_EL1, Physical Address Register
|
||||
pub const par_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0111, .CRm = 0b0100, .op2 = 0b000 };
|
||||
/// D19.2.109 REVIDR_EL1, Revision ID Register
|
||||
pub const revidr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b110 };
|
||||
/// D19.2.110 RGSR_EL1, Random Allocation Tag Seed Register
|
||||
pub const rgsr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b101 };
|
||||
/// D19.2.111 RMR_EL1, Reset Management Register (EL1)
|
||||
pub const rmr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b010 };
|
||||
/// D19.2.112 RMR_EL2, Reset Management Register (EL2)
|
||||
pub const rmr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b010 };
|
||||
/// D19.2.113 RMR_EL3, Reset Management Register (EL3)
|
||||
pub const rmr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b010 };
|
||||
/// D19.2.114 RNDR, Random Number
|
||||
pub const rndr: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b0010, .CRm = 0b0100, .op2 = 0b000 };
|
||||
/// D19.2.115 RNDRRS, Reseeded Random Number
|
||||
pub const rndrrs: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b0010, .CRm = 0b0100, .op2 = 0b001 };
|
||||
/// D19.2.116 RVBAR_EL1, Reset Vector Base Address Register (if EL2 and EL3 not implemented)
|
||||
pub const rvbar_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b001 };
|
||||
/// D19.2.117 RVBAR_EL2, Reset Vector Base Address Register (if EL3 not implemented)
|
||||
pub const rvbar_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b001 };
|
||||
/// D19.2.118 RVBAR_EL3, Reset Vector Base Address Register (if EL3 implemented)
|
||||
pub const rvbar_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b001 };
|
||||
/// D19.2.120 SCR_EL3, Secure Configuration Register
|
||||
pub const scr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0001, .op2 = 0b000 };
|
||||
/// D19.2.121 SCTLR2_EL1, System Control Register (EL1)
|
||||
pub const sctlr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b011 };
|
||||
/// D19.2.121 SCTLR2_EL12, System Control Register (EL12)
|
||||
pub const sctlr2_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b011 };
|
||||
/// D19.2.122 SCTLR2_EL2, System Control Register (EL2)
|
||||
pub const sctlr2_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b011 };
|
||||
/// D19.2.123 SCTLR2_EL3, System Control Register (EL3)
|
||||
pub const sctlr2_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b011 };
|
||||
/// D19.2.124 SCTLR_EL1, System Control Register (EL1)
|
||||
pub const sctlr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.124 SCTLR_EL12, System Control Register (EL12)
|
||||
pub const sctlr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.125 SCTLR_EL2, System Control Register (EL2)
|
||||
pub const sctlr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.126 SCTLR_EL3, System Control Register (EL3)
|
||||
pub const sctlr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.127 SCXTNUM_EL0, EL0 Read/Write Software Context Number
|
||||
pub const scxtnum_el0: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b111 };
|
||||
/// D19.2.128 SCXTNUM_EL1, EL1 Read/Write Software Context Number
|
||||
pub const scxtnum_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b111 };
|
||||
/// D19.2.128 SCXTNUM_EL12, EL12 Read/Write Software Context Number
|
||||
pub const scxtnum_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b111 };
|
||||
/// D19.2.129 SCXTNUM_EL2, EL2 Read/Write Software Context Number
|
||||
pub const scxtnum_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b111 };
|
||||
/// D19.2.130 SCXTNUM_EL3, EL3 Read/Write Software Context Number
|
||||
pub const scxtnum_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b111 };
|
||||
/// D19.2.131 SMCR_EL1, SME Control Register (EL1)
|
||||
pub const smcr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b110 };
|
||||
/// D19.2.131 SMCR_EL12, SME Control Register (EL12)
|
||||
pub const smcr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b110 };
|
||||
/// D19.2.132 SMCR_EL2, SME Control Register (EL2)
|
||||
pub const smcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b110 };
|
||||
/// D19.2.133 SMCR_EL3, SME Control Register (EL3)
|
||||
pub const smcr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b110 };
|
||||
/// D19.2.134 SMIDR_EL1, Streaming Mode Identification Register
|
||||
pub const smidr_el1: System = .{ .op0 = 0b11, .op1 = 0b001, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b110 };
|
||||
/// D19.2.135 SMPRIMAP_EL2, Streaming Mode Priority Mapping Register
|
||||
pub const smprimap_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b101 };
|
||||
/// D19.2.136 SMPRI_EL1, Streaming Mode Priority Register
|
||||
pub const smpri_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b100 };
|
||||
/// D19.2.137 TCR2_EL1, Extended Translation Control Register (EL1)
|
||||
pub const tcr2_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b011 };
|
||||
/// D19.2.137 TCR2_EL12, Extended Translation Control Register (EL12)
|
||||
pub const tcr2_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b011 };
|
||||
/// D19.2.138 TCR2_EL2, Extended Translation Control Register (EL2)
|
||||
pub const tcr2_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b011 };
|
||||
/// D19.2.139 TCR_EL1, Translation Control Register (EL1)
|
||||
pub const tcr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b010 };
|
||||
/// D19.2.139 TCR_EL12, Translation Control Register (EL12)
|
||||
pub const tcr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b010 };
|
||||
/// D19.2.140 TCR_EL2, Translation Control Register (EL2)
|
||||
pub const tcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b010 };
|
||||
/// D19.2.141 TCR_EL3, Translation Control Register (EL3)
|
||||
pub const tcr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b010 };
|
||||
/// D19.2.142 TFSRE0_EL1, Tag Fault Status Register (EL0)
|
||||
pub const tfsre0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0101, .CRm = 0b0110, .op2 = 0b001 };
|
||||
/// D19.2.143 TFSR_EL1, Tag Fault Status Register (EL1)
|
||||
pub const tfsr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0101, .CRm = 0b0110, .op2 = 0b000 };
|
||||
/// D19.2.143 TFSR_EL12, Tag Fault Status Register (EL12)
|
||||
pub const tfsr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0101, .CRm = 0b0110, .op2 = 0b000 };
|
||||
/// D19.2.144 TFSR_EL2, Tag Fault Status Register (EL2)
|
||||
pub const tfsr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0101, .CRm = 0b0110, .op2 = 0b000 };
|
||||
/// D19.2.145 TFSR_EL3, Tag Fault Status Register (EL3)
|
||||
pub const tfsr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0101, .CRm = 0b0110, .op2 = 0b000 };
|
||||
/// D19.2.146 TPIDR2_EL0, EL0 Read/Write Software Thread ID Register 2
|
||||
pub const tpidr2_el0: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b101 };
|
||||
/// D19.2.147 TPIDR_EL0, EL0 Read/Write Software Thread ID Register
|
||||
pub const tpidr_el0: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b010 };
|
||||
/// D19.2.148 TPIDR_EL1, EL1 Read/Write Software Thread ID Register
|
||||
pub const tpidr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b100 };
|
||||
/// D19.2.149 TPIDR_EL2, EL2 Read/Write Software Thread ID Register
|
||||
pub const tpidr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b010 };
|
||||
/// D19.2.150 TPIDR_EL3, EL3 Read/Write Software Thread ID Register
|
||||
pub const tpidr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b010 };
|
||||
/// D19.2.151 TPIDRRO_EL0, EL0 Read-Only Software Thread ID Register
|
||||
pub const tpidrro_el3: System = .{ .op0 = 0b11, .op1 = 0b011, .CRn = 0b1101, .CRm = 0b0000, .op2 = 0b011 };
|
||||
/// D19.2.152 TTBR0_EL1, Translation Table Base Register 0 (EL1)
|
||||
pub const ttbr0_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.152 TTBR0_EL12, Translation Table Base Register 0 (EL12)
|
||||
pub const ttbr0_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.153 TTBR0_EL2, Translation Table Base Register 0 (EL2)
|
||||
pub const ttbr0_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.154 TTBR0_EL3, Translation Table Base Register 0 (EL3)
|
||||
pub const ttbr0_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.155 TTBR1_EL1, Translation Table Base Register 1 (EL1)
|
||||
pub const ttbr1_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b001 };
|
||||
/// D19.2.155 TTBR1_EL12, Translation Table Base Register 1 (EL12)
|
||||
pub const ttbr1_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b001 };
|
||||
/// D19.2.156 TTBR1_EL2, Translation Table Base Register 1 (EL2)
|
||||
pub const ttbr1_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0000, .op2 = 0b001 };
|
||||
/// D19.2.157 VBAR_EL1, Vector Base Address Register (EL1)
|
||||
pub const vbar_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.157 VBAR_EL12, Vector Base Address Register (EL12)
|
||||
pub const vbar_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.158 VBAR_EL2, Vector Base Address Register (EL2)
|
||||
pub const vbar_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.159 VBAR_EL3, Vector Base Address Register (EL3)
|
||||
pub const vbar_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b1100, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.160 VMPIDR_EL2, Virtualization Multiprocessor ID Register
|
||||
pub const vmpidr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b101 };
|
||||
/// D19.2.161 VNCR_EL2, Virtual Nested Control Register
|
||||
pub const nvcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0010, .op2 = 0b000 };
|
||||
/// D19.2.162 VPIDR_EL2, Virtualization Processor ID Register
|
||||
pub const vpidr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0000, .CRm = 0b0000, .op2 = 0b000 };
|
||||
/// D19.2.163 VSTCR_EL2, Virtualization Secure Translation Control Register
|
||||
pub const vstcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0110, .op2 = 0b010 };
|
||||
/// D19.2.164 VSTTBR_EL2, Virtualization Secure Translation Table Base Register
|
||||
pub const vsttbr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0110, .op2 = 0b000 };
|
||||
/// D19.2.165 VTCR_EL2, Virtualization Translation Control Register
|
||||
pub const vtcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0001, .op2 = 0b010 };
|
||||
/// D19.2.166 VTTBR_EL2, Virtualization Translation Table Base Register
|
||||
pub const vttbr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0010, .CRm = 0b0001, .op2 = 0b000 };
|
||||
/// D19.2.167 ZCR_EL1, SVE Control Register (EL1)
|
||||
pub const zcr_el1: System = .{ .op0 = 0b11, .op1 = 0b000, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b000 };
|
||||
/// D19.2.167 ZCR_EL12, SVE Control Register (EL12)
|
||||
pub const zcr_el12: System = .{ .op0 = 0b11, .op1 = 0b101, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b000 };
|
||||
/// D19.2.168 ZCR_EL2, SVE Control Register (EL2)
|
||||
pub const zcr_el2: System = .{ .op0 = 0b11, .op1 = 0b100, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b000 };
|
||||
/// D19.2.169 ZCR_EL3, SVE Control Register (EL3)
|
||||
pub const zcr_el3: System = .{ .op0 = 0b11, .op1 = 0b110, .CRn = 0b0001, .CRm = 0b0010, .op2 = 0b000 };
|
||||
|
||||
pub fn parse(reg: []const u8) ?System {
|
||||
if (reg.len >= 10 and std.ascii.toLower(reg[0]) == 's') encoded: {
|
||||
var symbol_it = std.mem.splitScalar(u8, reg[1..], '_');
|
||||
const op0 = std.fmt.parseInt(u2, symbol_it.next() orelse break :encoded, 10) catch break :encoded;
|
||||
if (op0 < 0b10) break :encoded;
|
||||
const op1 = std.fmt.parseInt(u3, symbol_it.next() orelse break :encoded, 10) catch break :encoded;
|
||||
const n = symbol_it.next() orelse break :encoded;
|
||||
if (n.len == 0 or std.ascii.toLower(n[0]) != 'c') break :encoded;
|
||||
const CRn = std.fmt.parseInt(u4, n[1..], 10) catch break :encoded;
|
||||
const m = symbol_it.next() orelse break :encoded;
|
||||
if (m.len == 0 or std.ascii.toLower(m[0]) != 'c') break :encoded;
|
||||
const CRm = std.fmt.parseInt(u4, m[1..], 10) catch break :encoded;
|
||||
const op2 = std.fmt.parseInt(u3, symbol_it.next() orelse break :encoded, 10) catch break :encoded;
|
||||
if (symbol_it.next() != null) break :encoded;
|
||||
return .{ .op0 = op0, .op1 = op1, .CRn = CRn, .CRm = CRm, .op2 = op2 };
|
||||
}
|
||||
inline for (@typeInfo(System).@"struct".decls) |decl| {
|
||||
if (@TypeOf(@field(System, decl.name)) != System) continue;
|
||||
if (toLowerEqlAssertLower(reg, decl.name)) return @field(System, decl.name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
fn toLowerEqlAssertLower(lhs: []const u8, rhs: []const u8) bool {
|
||||
if (lhs.len != rhs.len) return false;
|
||||
for (lhs, rhs) |l, r| {
|
||||
assert(!std.ascii.isUpper(r));
|
||||
if (std.ascii.toLower(l) != r) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/// C1.2.4 Condition code
|
||||
@ -2385,12 +2801,7 @@ pub const Instruction = packed union {
|
||||
|
||||
pub const Group = packed struct {
|
||||
Rt: Register.Encoded,
|
||||
op2: u3,
|
||||
CRm: u4,
|
||||
CRn: u4,
|
||||
op1: u3,
|
||||
o0: u1,
|
||||
decoded20: u1 = 0b1,
|
||||
systemreg: Register.System,
|
||||
L: L,
|
||||
decoded22: u10 = 0b1101010100,
|
||||
};
|
||||
@ -2398,12 +2809,7 @@ pub const Instruction = packed union {
|
||||
/// C6.2.230 MSR (register)
|
||||
pub const Msr = packed struct {
|
||||
Rt: Register.Encoded,
|
||||
op2: u3,
|
||||
CRm: u4,
|
||||
CRn: u4,
|
||||
op1: u3,
|
||||
o0: u1,
|
||||
decoded20: u1 = 0b1,
|
||||
systemreg: Register.System,
|
||||
L: L = .msr,
|
||||
decoded22: u10 = 0b1101010100,
|
||||
};
|
||||
@ -2411,12 +2817,7 @@ pub const Instruction = packed union {
|
||||
/// C6.2.228 MRS
|
||||
pub const Mrs = packed struct {
|
||||
Rt: Register.Encoded,
|
||||
op2: u3,
|
||||
CRm: u4,
|
||||
CRn: u4,
|
||||
op1: u3,
|
||||
o0: u1,
|
||||
decoded20: u1 = 0b1,
|
||||
systemreg: Register.System,
|
||||
L: L = .mrs,
|
||||
decoded22: u10 = 0b1101010100,
|
||||
};
|
||||
@ -10585,30 +10986,22 @@ pub const Instruction = packed union {
|
||||
} } };
|
||||
}
|
||||
/// C6.2.228 MRS
|
||||
pub fn mrs(t: Register, op0: u2, op1: u3, n: u4, m: u4, op2: u3) Instruction {
|
||||
assert(t.format.integer == .doubleword);
|
||||
pub fn mrs(t: Register, systemreg: Register.System) Instruction {
|
||||
assert(t.format.integer == .doubleword and systemreg.op0 >= 0b10);
|
||||
return .{ .branch_exception_generating_system = .{ .system_register_move = .{
|
||||
.mrs = .{
|
||||
.Rt = t.alias.encode(.{}),
|
||||
.op2 = op2,
|
||||
.CRm = m,
|
||||
.CRn = n,
|
||||
.op1 = op1,
|
||||
.o0 = @intCast(op0 - 0b10),
|
||||
.systemreg = systemreg,
|
||||
},
|
||||
} } };
|
||||
}
|
||||
/// C6.2.230 MSR (register)
|
||||
pub fn msr(op0: u2, op1: u3, n: u4, m: u4, op2: u3, t: Register) Instruction {
|
||||
assert(t.format.integer == .doubleword);
|
||||
pub fn msr(systemreg: Register.System, t: Register) Instruction {
|
||||
assert(systemreg.op0 >= 0b10 and t.format.integer == .doubleword);
|
||||
return .{ .branch_exception_generating_system = .{ .system_register_move = .{
|
||||
.msr = .{
|
||||
.Rt = t.alias.encode(.{}),
|
||||
.op2 = op2,
|
||||
.CRm = m,
|
||||
.CRn = n,
|
||||
.op1 = op1,
|
||||
.o0 = @intCast(op0 - 0b10),
|
||||
.systemreg = systemreg,
|
||||
},
|
||||
} } };
|
||||
}
|
||||
|
||||
@ -851,11 +851,21 @@
|
||||
},
|
||||
// C6.2.228 MRS
|
||||
.{
|
||||
.pattern = "MRS <Xt>, CTR_EL0",
|
||||
.pattern = "MRS <Xt>, <systemreg>",
|
||||
.symbols = .{
|
||||
.Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
|
||||
.systemreg = .systemreg,
|
||||
},
|
||||
.encode = .{ .mrs, .Xt, 0b11, 0b011, 0b0000, 0b0000, 0b001 },
|
||||
.encode = .{ .mrs, .Xt, .systemreg },
|
||||
},
|
||||
// C6.2.230 MSR (register)
|
||||
.{
|
||||
.pattern = "MSR <systemreg>, <Xt>",
|
||||
.symbols = .{
|
||||
.systemreg = .systemreg,
|
||||
.Xt = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
|
||||
},
|
||||
.encode = .{ .msr, .systemreg, .Xt },
|
||||
},
|
||||
// C6.2.234 NEG
|
||||
.{
|
||||
|
||||
146
src/main.zig
146
src/main.zig
@ -4648,14 +4648,14 @@ const usage_init =
|
||||
fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
|
||||
dev.check(.init_command);
|
||||
|
||||
var strip = false;
|
||||
var template: enum { example, minimal } = .example;
|
||||
{
|
||||
var i: usize = 0;
|
||||
while (i < args.len) : (i += 1) {
|
||||
const arg = args[i];
|
||||
if (mem.startsWith(u8, arg, "-")) {
|
||||
if (mem.eql(u8, arg, "-s") or mem.eql(u8, arg, "--strip")) {
|
||||
strip = true;
|
||||
if (mem.eql(u8, arg, "-m") or mem.eql(u8, arg, "--minimal")) {
|
||||
template = .minimal;
|
||||
} else if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
|
||||
try fs.File.stdout().writeAll(usage_init);
|
||||
return cleanExit();
|
||||
@ -4668,40 +4668,79 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
|
||||
}
|
||||
}
|
||||
|
||||
var templates = findTemplates(gpa, arena, strip);
|
||||
defer templates.deinit();
|
||||
|
||||
const cwd_path = try introspect.getResolvedCwd(arena);
|
||||
const cwd_basename = fs.path.basename(cwd_path);
|
||||
const sanitized_root_name = try sanitizeExampleName(arena, cwd_basename);
|
||||
|
||||
const s = fs.path.sep_str;
|
||||
const template_paths = [_][]const u8{
|
||||
Package.build_zig_basename,
|
||||
Package.Manifest.basename,
|
||||
"src" ++ s ++ "main.zig",
|
||||
"src" ++ s ++ "root.zig",
|
||||
};
|
||||
var ok_count: usize = 0;
|
||||
|
||||
const fingerprint: Package.Fingerprint = .generate(sanitized_root_name);
|
||||
|
||||
for (template_paths) |template_path| {
|
||||
if (templates.write(arena, fs.cwd(), sanitized_root_name, template_path, fingerprint)) |_| {
|
||||
std.log.info("created {s}", .{template_path});
|
||||
ok_count += 1;
|
||||
} else |err| switch (err) {
|
||||
error.PathAlreadyExists => std.log.info("preserving already existing file: {s}", .{
|
||||
template_path,
|
||||
}),
|
||||
else => std.log.err("unable to write {s}: {s}\n", .{ template_path, @errorName(err) }),
|
||||
}
|
||||
}
|
||||
switch (template) {
|
||||
.example => {
|
||||
var templates = findTemplates(gpa, arena);
|
||||
defer templates.deinit();
|
||||
|
||||
if (ok_count == template_paths.len) {
|
||||
std.log.info("see `zig build --help` for a menu of options", .{});
|
||||
const s = fs.path.sep_str;
|
||||
const template_paths = [_][]const u8{
|
||||
Package.build_zig_basename,
|
||||
Package.Manifest.basename,
|
||||
"src" ++ s ++ "main.zig",
|
||||
"src" ++ s ++ "root.zig",
|
||||
};
|
||||
var ok_count: usize = 0;
|
||||
|
||||
for (template_paths) |template_path| {
|
||||
if (templates.write(arena, fs.cwd(), sanitized_root_name, template_path, fingerprint)) |_| {
|
||||
std.log.info("created {s}", .{template_path});
|
||||
ok_count += 1;
|
||||
} else |err| switch (err) {
|
||||
error.PathAlreadyExists => std.log.info("preserving already existing file: {s}", .{
|
||||
template_path,
|
||||
}),
|
||||
else => std.log.err("unable to write {s}: {s}\n", .{ template_path, @errorName(err) }),
|
||||
}
|
||||
}
|
||||
|
||||
if (ok_count == template_paths.len) {
|
||||
std.log.info("see `zig build --help` for a menu of options", .{});
|
||||
}
|
||||
return cleanExit();
|
||||
},
|
||||
.minimal => {
|
||||
writeSimpleTemplateFile(Package.Manifest.basename,
|
||||
\\.{{
|
||||
\\ .name = .{s},
|
||||
\\ .version = "{s}",
|
||||
\\ .paths = .{{""}},
|
||||
\\ .fingerprint = 0x{x},
|
||||
\\}}
|
||||
\\
|
||||
, .{
|
||||
sanitized_root_name,
|
||||
build_options.version,
|
||||
fingerprint.int(),
|
||||
}) catch |err| switch (err) {
|
||||
else => fatal("failed to create '{s}': {s}", .{ Package.Manifest.basename, @errorName(err) }),
|
||||
error.PathAlreadyExists => fatal("refusing to overwrite '{s}'", .{Package.Manifest.basename}),
|
||||
};
|
||||
writeSimpleTemplateFile(Package.build_zig_basename,
|
||||
\\const std = @import("std");
|
||||
\\pub fn build(b: *std.Build) void {{
|
||||
\\ _ = b; // stub
|
||||
\\}}
|
||||
\\
|
||||
, .{}) catch |err| switch (err) {
|
||||
else => fatal("failed to create '{s}': {s}", .{ Package.build_zig_basename, @errorName(err) }),
|
||||
// `build.zig` already existing is okay: the user has just used `zig init` to set up
|
||||
// their `build.zig.zon` *after* writing their `build.zig`. So this one isn't fatal.
|
||||
error.PathAlreadyExists => {
|
||||
std.log.info("successfully populated '{s}', preserving existing '{s}'", .{ Package.Manifest.basename, Package.build_zig_basename });
|
||||
return cleanExit();
|
||||
},
|
||||
};
|
||||
std.log.info("successfully populated '{s}' and '{s}'", .{ Package.Manifest.basename, Package.build_zig_basename });
|
||||
return cleanExit();
|
||||
},
|
||||
}
|
||||
return cleanExit();
|
||||
}
|
||||
|
||||
fn sanitizeExampleName(arena: Allocator, bytes: []const u8) error{OutOfMemory}![]const u8 {
|
||||
@ -7229,13 +7268,20 @@ fn loadManifest(
|
||||
0,
|
||||
) catch |err| switch (err) {
|
||||
error.FileNotFound => {
|
||||
const fingerprint: Package.Fingerprint = .generate(options.root_name);
|
||||
var templates = findTemplates(gpa, arena, true);
|
||||
defer templates.deinit();
|
||||
templates.write(arena, options.dir, options.root_name, Package.Manifest.basename, fingerprint) catch |e| {
|
||||
fatal("unable to write {s}: {s}", .{
|
||||
Package.Manifest.basename, @errorName(e),
|
||||
});
|
||||
writeSimpleTemplateFile(Package.Manifest.basename,
|
||||
\\.{{
|
||||
\\ .name = .{s},
|
||||
\\ .version = "{s}",
|
||||
\\ .paths = .{{""}},
|
||||
\\ .fingerprint = 0x{x},
|
||||
\\}}
|
||||
\\
|
||||
, .{
|
||||
options.root_name,
|
||||
build_options.version,
|
||||
Package.Fingerprint.generate(options.root_name).int(),
|
||||
}) catch |e| {
|
||||
fatal("unable to write {s}: {s}", .{ Package.Manifest.basename, @errorName(e) });
|
||||
};
|
||||
continue;
|
||||
},
|
||||
@ -7276,7 +7322,6 @@ const Templates = struct {
|
||||
zig_lib_directory: Cache.Directory,
|
||||
dir: fs.Dir,
|
||||
buffer: std.ArrayList(u8),
|
||||
strip: bool,
|
||||
|
||||
fn deinit(templates: *Templates) void {
|
||||
templates.zig_lib_directory.handle.close();
|
||||
@ -7305,23 +7350,9 @@ const Templates = struct {
|
||||
};
|
||||
templates.buffer.clearRetainingCapacity();
|
||||
try templates.buffer.ensureUnusedCapacity(contents.len);
|
||||
var new_line = templates.strip;
|
||||
var i: usize = 0;
|
||||
while (i < contents.len) {
|
||||
if (new_line) {
|
||||
const trimmed = std.mem.trimLeft(u8, contents[i..], " ");
|
||||
if (std.mem.startsWith(u8, trimmed, "//")) {
|
||||
i += std.mem.indexOfScalar(u8, contents[i..], '\n') orelse break;
|
||||
i += 1;
|
||||
continue;
|
||||
} else {
|
||||
new_line = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (templates.strip and contents[i] == '\n') {
|
||||
new_line = true;
|
||||
} else if (contents[i] == '_' or contents[i] == '.') {
|
||||
if (contents[i] == '_' or contents[i] == '.') {
|
||||
// Both '_' and '.' are allowed because depending on the context
|
||||
// one prefix will be valid, while the other might not.
|
||||
if (std.mem.startsWith(u8, contents[i + 1 ..], "NAME")) {
|
||||
@ -7350,8 +7381,16 @@ const Templates = struct {
|
||||
});
|
||||
}
|
||||
};
|
||||
fn writeSimpleTemplateFile(file_name: []const u8, comptime fmt: []const u8, args: anytype) !void {
|
||||
const f = try fs.cwd().createFile(file_name, .{ .exclusive = true });
|
||||
defer f.close();
|
||||
var buf: [4096]u8 = undefined;
|
||||
var fw = f.writer(&buf);
|
||||
try fw.interface.print(fmt, args);
|
||||
try fw.interface.flush();
|
||||
}
|
||||
|
||||
fn findTemplates(gpa: Allocator, arena: Allocator, strip: bool) Templates {
|
||||
fn findTemplates(gpa: Allocator, arena: Allocator) Templates {
|
||||
const cwd_path = introspect.getResolvedCwd(arena) catch |err| {
|
||||
fatal("unable to get cwd: {s}", .{@errorName(err)});
|
||||
};
|
||||
@ -7375,7 +7414,6 @@ fn findTemplates(gpa: Allocator, arena: Allocator, strip: bool) Templates {
|
||||
.zig_lib_directory = zig_lib_directory,
|
||||
.dir = template_dir,
|
||||
.buffer = std.ArrayList(u8).init(gpa),
|
||||
.strip = strip,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -316,10 +316,10 @@ int main(int argc, char **argv) {
|
||||
"}\n"
|
||||
"\n"
|
||||
"static uint32_t memory_grow(uint8_t **m, uint32_t *p, uint32_t *c, uint32_t n) {\n"
|
||||
" uint8_t *new_m = *m;\n"
|
||||
" uint32_t r = *p;\n"
|
||||
" uint32_t new_p = r + n;\n"
|
||||
" if (new_p > UINT32_C(0xFFFF)) return UINT32_C(0xFFFFFFFF);\n"
|
||||
" uint8_t *new_m = *m;\n"
|
||||
" uint32_t new_c = *c;\n"
|
||||
" if (new_c < new_p) {\n"
|
||||
" do new_c += new_c / 2 + 8; while (new_c < new_p);\n"
|
||||
|
||||
@ -471,7 +471,6 @@ fn testPointerToVoidReturnType2() *const void {
|
||||
}
|
||||
|
||||
test "array 2D const double ptr" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
@ -484,7 +483,6 @@ test "array 2D const double ptr" {
|
||||
}
|
||||
|
||||
test "array 2D const double ptr with offset" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
@ -497,7 +495,6 @@ test "array 2D const double ptr with offset" {
|
||||
}
|
||||
|
||||
test "array 3D const double ptr with offset" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
||||
@ -1816,7 +1816,6 @@ test "peer type resolution: C pointer and @TypeOf(null)" {
|
||||
}
|
||||
|
||||
test "peer type resolution: three-way resolution combines error set and optional" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
|
||||
|
||||
@ -436,7 +436,6 @@ test "pointer sentinel with optional element" {
|
||||
}
|
||||
|
||||
test "pointer sentinel with +inf" {
|
||||
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
|
||||
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
|
||||
|
||||
@ -2016,6 +2016,16 @@ pub fn addCliTests(b: *std.Build) *Step {
|
||||
step.dependOn(&cleanup.step);
|
||||
}
|
||||
|
||||
{
|
||||
// Test `zig init -m`.
|
||||
const tmp_path = b.makeTempPath();
|
||||
const init_exe = b.addSystemCommand(&.{ b.graph.zig_exe, "init", "-m" });
|
||||
init_exe.setCwd(.{ .cwd_relative = tmp_path });
|
||||
init_exe.setName("zig init -m");
|
||||
init_exe.expectStdOutEqual("");
|
||||
init_exe.expectStdErrEqual("info: successfully populated 'build.zig.zon' and 'build.zig'\n");
|
||||
}
|
||||
|
||||
// Test Godbolt API
|
||||
if (builtin.os.tag == .linux and builtin.cpu.arch == .x86_64) {
|
||||
const tmp_path = b.makeTempPath();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user