mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
Merge pull request #24856 from jacobly0/aarch64-oom
aarch64: more assembler instructions
This commit is contained in:
commit
6d7c6a0f4e
@ -6,11 +6,9 @@ pub const Operand = union(enum) {
|
||||
};
|
||||
|
||||
pub fn nextInstruction(as: *Assemble) !?Instruction {
|
||||
@setEvalBranchQuota(140_000);
|
||||
comptime var ct_token_buf: [token_buf_len]u8 = undefined;
|
||||
var token_buf: [token_buf_len]u8 = undefined;
|
||||
const original_source = while (true) {
|
||||
const original_source = as.source;
|
||||
var token_buf: [token_buf_len]u8 = undefined;
|
||||
const source_token = try as.nextToken(&token_buf, .{});
|
||||
switch (source_token.len) {
|
||||
0 => return null,
|
||||
@ -27,73 +25,9 @@ pub fn nextInstruction(as: *Assemble) !?Instruction {
|
||||
\\=========================
|
||||
\\
|
||||
, .{std.zig.fmtString(std.mem.span(original_source))});
|
||||
inline for (instructions) |instruction| {
|
||||
next_pattern: {
|
||||
as.source = original_source;
|
||||
const Symbols = @TypeOf(instruction.symbols);
|
||||
var symbols: Symbols: {
|
||||
const symbols = @typeInfo(Symbols).@"struct".fields;
|
||||
var symbol_fields: [symbols.len]std.builtin.Type.StructField = undefined;
|
||||
for (&symbol_fields, symbols) |*symbol_field, symbol| {
|
||||
const Storage = zonCast(SymbolSpec, @field(instruction.symbols, symbol.name), .{}).Storage();
|
||||
symbol_field.* = .{
|
||||
.name = symbol.name,
|
||||
.type = Storage,
|
||||
.default_value_ptr = null,
|
||||
.is_comptime = false,
|
||||
.alignment = @alignOf(Storage),
|
||||
};
|
||||
}
|
||||
break :Symbols @Type(.{ .@"struct" = .{
|
||||
.layout = .auto,
|
||||
.fields = &symbol_fields,
|
||||
.decls = &.{},
|
||||
.is_tuple = false,
|
||||
} });
|
||||
} = undefined;
|
||||
const Symbol = std.meta.FieldEnum(Symbols);
|
||||
comptime var unused_symbols: std.enums.EnumSet(Symbol) = .initFull();
|
||||
comptime var pattern_as: Assemble = .{ .source = instruction.pattern, .operands = undefined };
|
||||
inline while (true) {
|
||||
const pattern_token = comptime pattern_as.nextToken(&ct_token_buf, .{ .placeholders = true }) catch |err|
|
||||
@compileError(@errorName(err) ++ " while parsing '" ++ instruction.pattern ++ "'");
|
||||
const source_token = try as.nextToken(&token_buf, .{ .operands = true });
|
||||
log.debug("\"{f}\" -> \"{f}\"", .{
|
||||
std.zig.fmtString(pattern_token),
|
||||
std.zig.fmtString(source_token),
|
||||
});
|
||||
if (pattern_token.len == 0) {
|
||||
comptime var unused_symbol_it = unused_symbols.iterator();
|
||||
inline while (comptime unused_symbol_it.next()) |unused_symbol|
|
||||
@compileError(@tagName(unused_symbol) ++ " unused while parsing '" ++ instruction.pattern ++ "'");
|
||||
switch (source_token.len) {
|
||||
0 => {},
|
||||
else => switch (source_token[0]) {
|
||||
else => break :next_pattern,
|
||||
'\n', ';' => {},
|
||||
},
|
||||
}
|
||||
const encode = @field(Instruction, @tagName(instruction.encode[0]));
|
||||
const Encode = @TypeOf(encode);
|
||||
var args: std.meta.ArgsTuple(Encode) = undefined;
|
||||
inline for (&args, @typeInfo(Encode).@"fn".params, 1..instruction.encode.len) |*arg, param, encode_index|
|
||||
arg.* = zonCast(param.type.?, instruction.encode[encode_index], symbols);
|
||||
return @call(.auto, encode, args);
|
||||
} else if (pattern_token[0] == '<') {
|
||||
const symbol_name = comptime pattern_token[1 .. std.mem.indexOfScalarPos(u8, pattern_token, 1, '|') orelse
|
||||
pattern_token.len - 1];
|
||||
const symbol = @field(Symbol, symbol_name);
|
||||
const symbol_ptr = &@field(symbols, symbol_name);
|
||||
const symbol_value = zonCast(SymbolSpec, @field(instruction.symbols, symbol_name), .{}).parse(source_token) orelse break :next_pattern;
|
||||
if (comptime unused_symbols.contains(symbol)) {
|
||||
log.debug("{s} = {any}", .{ symbol_name, symbol_value });
|
||||
symbol_ptr.* = symbol_value;
|
||||
comptime unused_symbols.remove(symbol);
|
||||
} else if (symbol_ptr.* != symbol_value) break :next_pattern;
|
||||
} else if (!toUpperEqlAssertUpper(source_token, pattern_token)) break :next_pattern;
|
||||
}
|
||||
}
|
||||
log.debug("'{s}' not matched...", .{instruction.pattern});
|
||||
for (matchers) |matcher| {
|
||||
as.source = original_source;
|
||||
if (try matcher(as)) |result| return result;
|
||||
}
|
||||
as.source = original_source;
|
||||
log.debug("Nothing matched!\n", .{});
|
||||
@ -106,6 +40,12 @@ fn zonCast(comptime Result: type, zon_value: anytype, symbols: anytype) Result {
|
||||
switch (@typeInfo(ZonValue)) {
|
||||
.void, .bool, .int, .float, .pointer, .comptime_float, .comptime_int, .@"enum" => return zon_value,
|
||||
.@"struct" => |zon_struct| switch (@typeInfo(Result)) {
|
||||
.pointer => |result_pointer| {
|
||||
comptime assert(result_pointer.size == .slice and result_pointer.is_const);
|
||||
var elems: [zon_value.len]result_pointer.child = undefined;
|
||||
inline for (&elems, zon_value) |*elem, zon_elem| elem.* = zonCast(result_pointer.child, zon_elem, symbols);
|
||||
return &elems;
|
||||
},
|
||||
.@"struct" => |result_struct| {
|
||||
comptime var used_zon_fields = 0;
|
||||
var result: Result = undefined;
|
||||
@ -158,6 +98,103 @@ fn zonCast(comptime Result: type, zon_value: anytype, symbols: anytype) Result {
|
||||
}
|
||||
}
|
||||
|
||||
const matchers = matchers: {
|
||||
const instructions = @import("instructions.zon");
|
||||
var mut_matchers: [instructions.len]*const fn (as: *Assemble) error{InvalidSyntax}!?Instruction = undefined;
|
||||
for (instructions, &mut_matchers) |instruction, *matcher| matcher.* = struct {
|
||||
fn match(as: *Assemble) !?Instruction {
|
||||
comptime for (@typeInfo(@TypeOf(instruction)).@"struct".fields) |field| {
|
||||
if (std.mem.eql(u8, field.name, "requires")) continue;
|
||||
if (std.mem.eql(u8, field.name, "pattern")) continue;
|
||||
if (std.mem.eql(u8, field.name, "symbols")) continue;
|
||||
if (std.mem.eql(u8, field.name, "encode")) continue;
|
||||
@compileError("unexpected field '" ++ field.name ++ "'");
|
||||
};
|
||||
if (@hasField(@TypeOf(instruction), "requires")) _ = zonCast(
|
||||
[]const std.Target.aarch64.Feature,
|
||||
instruction.requires,
|
||||
.{},
|
||||
);
|
||||
var symbols: Symbols: {
|
||||
const symbols = @typeInfo(@TypeOf(instruction.symbols)).@"struct".fields;
|
||||
var symbol_fields: [symbols.len]std.builtin.Type.StructField = undefined;
|
||||
for (&symbol_fields, symbols) |*symbol_field, symbol| {
|
||||
const Storage = zonCast(SymbolSpec, @field(instruction.symbols, symbol.name), .{}).Storage();
|
||||
symbol_field.* = .{
|
||||
.name = symbol.name,
|
||||
.type = Storage,
|
||||
.default_value_ptr = null,
|
||||
.is_comptime = false,
|
||||
.alignment = @alignOf(Storage),
|
||||
};
|
||||
}
|
||||
break :Symbols @Type(.{ .@"struct" = .{
|
||||
.layout = .auto,
|
||||
.fields = &symbol_fields,
|
||||
.decls = &.{},
|
||||
.is_tuple = false,
|
||||
} });
|
||||
} = undefined;
|
||||
const Symbol = std.meta.FieldEnum(@TypeOf(instruction.symbols));
|
||||
comptime var unused_symbols: std.enums.EnumSet(Symbol) = .initFull();
|
||||
comptime var pattern_as: Assemble = .{ .source = instruction.pattern, .operands = undefined };
|
||||
inline while (true) {
|
||||
comptime var ct_token_buf: [token_buf_len]u8 = undefined;
|
||||
var token_buf: [token_buf_len]u8 = undefined;
|
||||
const pattern_token = comptime pattern_as.nextToken(&ct_token_buf, .{ .placeholders = true }) catch |err|
|
||||
@compileError(@errorName(err) ++ " while parsing '" ++ instruction.pattern ++ "'");
|
||||
const source_token = try as.nextToken(&token_buf, .{ .operands = true });
|
||||
log.debug("\"{f}\" -> \"{f}\"", .{
|
||||
std.zig.fmtString(pattern_token),
|
||||
std.zig.fmtString(source_token),
|
||||
});
|
||||
if (pattern_token.len == 0) {
|
||||
comptime var unused_symbol_it = unused_symbols.iterator();
|
||||
inline while (comptime unused_symbol_it.next()) |unused_symbol|
|
||||
@compileError(@tagName(unused_symbol) ++ " unused while parsing '" ++ instruction.pattern ++ "'");
|
||||
switch (source_token.len) {
|
||||
0 => {},
|
||||
else => switch (source_token[0]) {
|
||||
else => {
|
||||
log.debug("'{s}' not matched...", .{instruction.pattern});
|
||||
return null;
|
||||
},
|
||||
'\n', ';' => {},
|
||||
},
|
||||
}
|
||||
const encode = @field(Instruction, @tagName(instruction.encode[0]));
|
||||
const Encode = @TypeOf(encode);
|
||||
var args: std.meta.ArgsTuple(Encode) = undefined;
|
||||
inline for (&args, @typeInfo(Encode).@"fn".params, 1..instruction.encode.len) |*arg, param, encode_index|
|
||||
arg.* = zonCast(param.type.?, instruction.encode[encode_index], symbols);
|
||||
return @call(.auto, encode, args);
|
||||
} else if (pattern_token[0] == '<') {
|
||||
const symbol_name = comptime pattern_token[1 .. std.mem.indexOfScalarPos(u8, pattern_token, 1, '|') orelse
|
||||
pattern_token.len - 1];
|
||||
const symbol = @field(Symbol, symbol_name);
|
||||
const symbol_ptr = &@field(symbols, symbol_name);
|
||||
const symbol_value = zonCast(SymbolSpec, @field(instruction.symbols, symbol_name), .{}).parse(source_token) orelse {
|
||||
log.debug("'{s}' not matched...", .{instruction.pattern});
|
||||
return null;
|
||||
};
|
||||
if (comptime unused_symbols.contains(symbol)) {
|
||||
log.debug("{s} = {any}", .{ symbol_name, symbol_value });
|
||||
symbol_ptr.* = symbol_value;
|
||||
comptime unused_symbols.remove(symbol);
|
||||
} else if (symbol_ptr.* != symbol_value) {
|
||||
log.debug("'{s}' not matched...", .{instruction.pattern});
|
||||
return null;
|
||||
}
|
||||
} else if (!toUpperEqlAssertUpper(source_token, pattern_token)) {
|
||||
log.debug("'{s}' not matched...", .{instruction.pattern});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}.match;
|
||||
break :matchers mut_matchers;
|
||||
};
|
||||
|
||||
fn toUpperEqlAssertUpper(lhs: []const u8, rhs: []const u8) bool {
|
||||
if (lhs.len != rhs.len) return false;
|
||||
for (lhs, rhs) |l, r| {
|
||||
@ -281,9 +318,10 @@ const SymbolSpec = union(enum) {
|
||||
multiple_of: ?comptime_int = null,
|
||||
min_valid: ?comptime_int = null,
|
||||
max_valid: ?comptime_int = null,
|
||||
adjust: enum { none, neg_wrap, dec } = .none,
|
||||
},
|
||||
fimm: struct { only_valid: ?f16 = null },
|
||||
extend: struct { size: aarch64.encoding.Register.GeneralSize },
|
||||
extend: struct { size: ?aarch64.encoding.Register.GeneralSize = null },
|
||||
shift: struct { allow_ror: bool = true },
|
||||
barrier: struct { only_sy: bool = false },
|
||||
|
||||
@ -293,7 +331,7 @@ const SymbolSpec = union(enum) {
|
||||
.reg => aarch64.encoding.Register,
|
||||
.arrangement => aarch64.encoding.Register.Arrangement,
|
||||
.systemreg => aarch64.encoding.Register.System,
|
||||
.imm => |imm| @Type(.{ .int = imm.type }),
|
||||
.imm => |imm_spec| @Type(.{ .int = imm_spec.type }),
|
||||
.fimm => f16,
|
||||
.extend => Instruction.DataProcessingRegister.AddSubtractExtendedRegister.Option,
|
||||
.shift => Instruction.DataProcessingRegister.Shift.Op,
|
||||
@ -372,7 +410,13 @@ const SymbolSpec = union(enum) {
|
||||
return systemreg;
|
||||
},
|
||||
.imm => |imm_spec| {
|
||||
const imm = std.fmt.parseInt(Result, token, 0) catch {
|
||||
const imm = std.fmt.parseInt(@Type(.{ .int = .{
|
||||
.signedness = imm_spec.type.signedness,
|
||||
.bits = switch (imm_spec.adjust) {
|
||||
.none, .neg_wrap => imm_spec.type.bits,
|
||||
.dec => imm_spec.type.bits + 1,
|
||||
},
|
||||
} }), token, 0) catch {
|
||||
log.debug("invalid immediate: \"{f}\"", .{std.zig.fmtString(token)});
|
||||
return null;
|
||||
};
|
||||
@ -388,7 +432,14 @@ const SymbolSpec = union(enum) {
|
||||
log.debug("out of range immediate: \"{f}\"", .{std.zig.fmtString(token)});
|
||||
return null;
|
||||
};
|
||||
return imm;
|
||||
return switch (imm_spec.adjust) {
|
||||
.none => imm,
|
||||
.neg_wrap => -%imm,
|
||||
.dec => std.math.cast(Result, imm - 1) orelse {
|
||||
log.debug("out of range immediate: \"{f}\"", .{std.zig.fmtString(token)});
|
||||
return null;
|
||||
},
|
||||
};
|
||||
},
|
||||
.fimm => |fimm_spec| {
|
||||
const full_fimm = std.fmt.parseFloat(f128, token) catch {
|
||||
@ -433,10 +484,10 @@ const SymbolSpec = union(enum) {
|
||||
log.debug("invalid extend: \"{f}\"", .{std.zig.fmtString(token)});
|
||||
return null;
|
||||
};
|
||||
if (extend.sf() != extend_spec.size) {
|
||||
if (extend_spec.size) |size| if (extend.sf() != size) {
|
||||
log.debug("invalid extend: \"{f}\"", .{std.zig.fmtString(token)});
|
||||
return null;
|
||||
}
|
||||
};
|
||||
return extend;
|
||||
},
|
||||
.shift => |shift_spec| {
|
||||
@ -488,6 +539,16 @@ const SymbolSpec = union(enum) {
|
||||
test "add sub" {
|
||||
var as: Assemble = .{
|
||||
.source =
|
||||
\\ adc w0, w0, w1
|
||||
\\ adc w2, w3, w4
|
||||
\\ adc w5, w5, wzr
|
||||
\\ adc w6, w7, wzr
|
||||
\\
|
||||
\\ adcs w0, w0, w1
|
||||
\\ adcs w2, w3, w4
|
||||
\\ adcs w5, w5, wzr
|
||||
\\ adcs w6, w7, wzr
|
||||
\\
|
||||
\\ add w0, w0, w1
|
||||
\\ add w2, w3, w4
|
||||
\\ add wsp, w5, w6
|
||||
@ -513,13 +574,13 @@ test "add sub" {
|
||||
\\ add w0, w0, w1
|
||||
\\ add w2, w3, w4, uxtb #0
|
||||
\\ add wsp, w5, w6, uxth #1
|
||||
\\ add w7, wsp, w8, uxtw #0
|
||||
\\ add wsp, wsp, w9, uxtw #2
|
||||
\\ add w10, w10, wzr, uxtw #3
|
||||
\\ add w7, wsp, w8, uxtw #2
|
||||
\\ add wsp, wsp, w9, uxtx #0
|
||||
\\ add w10, w10, wzr, uxtx #3
|
||||
\\ add w11, w12, wzr, sxtb #4
|
||||
\\ add wsp, w13, wzr, sxth #0
|
||||
\\ add w14, wsp, wzr, sxtw #1
|
||||
\\ add wsp, wsp, wzr, sxtw #2
|
||||
\\ add wsp, wsp, wzr, sxtx #2
|
||||
\\
|
||||
\\ add x0, x0, x1
|
||||
\\ add x2, x3, w4, uxtb #0
|
||||
@ -582,6 +643,125 @@ test "add sub" {
|
||||
\\ add xzr, xzr, x13, asr #0x1F
|
||||
\\ add xzr, xzr, xzr, asr #0x3f
|
||||
\\
|
||||
\\ addg x0, sp, #0, #0xf
|
||||
\\ addg sp, x1, #0x3f0, #0
|
||||
\\
|
||||
\\ adds w0, w0, w1
|
||||
\\ adds w2, w3, w4
|
||||
\\ adds w5, w5, w6
|
||||
\\ adds w7, wsp, w8
|
||||
\\ adds w9, wsp, w9
|
||||
\\ adds w10, w10, wzr
|
||||
\\ adds w11, w12, wzr
|
||||
\\ adds wzr, w13, wzr
|
||||
\\ adds w14, wsp, wzr
|
||||
\\ adds wzr, wsp, wzr
|
||||
\\
|
||||
\\ adds x0, x0, x1
|
||||
\\ adds x2, x3, x4
|
||||
\\ adds x5, x5, x6
|
||||
\\ adds x7, sp, x8
|
||||
\\ adds x9, sp, x9
|
||||
\\ adds x10, x10, xzr
|
||||
\\ adds x11, x12, xzr
|
||||
\\ adds xzr, x13, xzr
|
||||
\\ adds x14, sp, xzr
|
||||
\\ adds xzr, sp, xzr
|
||||
\\
|
||||
\\ adds w0, w0, w1
|
||||
\\ adds w2, w3, w4, uxtb #0
|
||||
\\ adds wzr, w5, w6, uxth #1
|
||||
\\ adds w7, wsp, w8, uxtw #2
|
||||
\\ adds w9, wsp, w9, uxtx #0
|
||||
\\ adds w10, w10, wzr, uxtx #3
|
||||
\\ adds w11, w12, wzr, sxtb #4
|
||||
\\ adds wzr, w13, wzr, sxth #0
|
||||
\\ adds w14, wsp, wzr, sxtw #1
|
||||
\\ adds wzr, wsp, wzr, sxtx #2
|
||||
\\
|
||||
\\ adds x0, x0, x1
|
||||
\\ adds x2, x3, w4, uxtb #0
|
||||
\\ adds xzr, x5, w6, uxth #1
|
||||
\\ adds x7, sp, w8, uxtw #2
|
||||
\\ adds xzr, sp, x9, uxtx #0
|
||||
\\ adds x10, x10, xzr, uxtx #3
|
||||
\\ adds x11, x12, wzr, sxtb #4
|
||||
\\ adds xzr, x13, wzr, sxth #0
|
||||
\\ adds x14, sp, wzr, sxtw #1
|
||||
\\ adds xzr, sp, xzr, sxtx #2
|
||||
\\
|
||||
\\ adds w0, w0, #0
|
||||
\\ adds w0, w1, #1, lsl #0
|
||||
\\ adds wzr, w2, #2, lsl #12
|
||||
\\ adds w3, wsp, #3, lsl #0
|
||||
\\ adds wzr, wsp, #4095, lsl #12
|
||||
\\ adds w0, w1, #0
|
||||
\\ adds w2, w3, #0, lsl #0
|
||||
\\ adds w4, wsp, #0
|
||||
\\ adds w5, wsp, #0, lsl #0
|
||||
\\ adds wzr, w6, #0
|
||||
\\ adds wzr, w7, #0, lsl #0
|
||||
\\ adds wzr, wsp, #0
|
||||
\\ adds wzr, wsp, #0, lsl #0
|
||||
\\
|
||||
\\ adds x0, x0, #0
|
||||
\\ adds x0, x1, #1, lsl #0
|
||||
\\ adds xzr, x2, #2, lsl #12
|
||||
\\ adds x3, sp, #3, lsl #0
|
||||
\\ adds xzr, sp, #4095, lsl #12
|
||||
\\ adds x0, x1, #0
|
||||
\\ adds x2, x3, #0, lsl #0
|
||||
\\ adds x4, sp, #0
|
||||
\\ adds x5, sp, #0, lsl #0
|
||||
\\ adds xzr, x6, #0
|
||||
\\ adds xzr, x7, #0, lsl #0
|
||||
\\ adds xzr, sp, #0
|
||||
\\ adds xzr, sp, #0, lsl #0
|
||||
\\
|
||||
\\ adds w0, w0, w0
|
||||
\\ adds w1, w1, w2, lsl #0
|
||||
\\ adds w3, w4, w5, lsl #1
|
||||
\\ adds w6, w6, wzr, lsl #31
|
||||
\\ adds w7, wzr, w8, lsr #0
|
||||
\\ adds w9, wzr, wzr, lsr #30
|
||||
\\ adds wzr, w10, w11, lsr #31
|
||||
\\ adds wzr, w12, wzr, asr #0x0
|
||||
\\ adds wzr, wzr, w13, asr #0x10
|
||||
\\ adds wzr, wzr, wzr, asr #0x1f
|
||||
\\
|
||||
\\ adds x0, x0, x0
|
||||
\\ adds x1, x1, x2, lsl #0
|
||||
\\ adds x3, x4, x5, lsl #1
|
||||
\\ adds x6, x6, xzr, lsl #63
|
||||
\\ adds x7, xzr, x8, lsr #0
|
||||
\\ adds x9, xzr, xzr, lsr #62
|
||||
\\ adds xzr, x10, x11, lsr #63
|
||||
\\ adds xzr, x12, xzr, asr #0x0
|
||||
\\ adds xzr, xzr, x13, asr #0x1F
|
||||
\\ adds xzr, xzr, xzr, asr #0x3f
|
||||
\\
|
||||
\\ neg w0, w0
|
||||
\\ neg w1, w2, lsl #0
|
||||
\\ neg w3, wzr, lsl #7
|
||||
\\ neg wzr, w4, lsr #14
|
||||
\\ neg wzr, wzr, asr #21
|
||||
\\
|
||||
\\ neg x0, x0
|
||||
\\ neg x1, x2, lsl #0
|
||||
\\ neg x3, xzr, lsl #11
|
||||
\\ neg xzr, x4, lsr #22
|
||||
\\ neg xzr, xzr, asr #33
|
||||
\\
|
||||
\\ sbc w0, w0, w1
|
||||
\\ sbc w2, w3, w4
|
||||
\\ sbc w5, w5, wzr
|
||||
\\ sbc w6, w7, wzr
|
||||
\\
|
||||
\\ sbcs w0, w0, w1
|
||||
\\ sbcs w2, w3, w4
|
||||
\\ sbcs w5, w5, wzr
|
||||
\\ sbcs w6, w7, wzr
|
||||
\\
|
||||
\\ sub w0, w0, w1
|
||||
\\ sub w2, w3, w4
|
||||
\\ sub wsp, w5, w6
|
||||
@ -607,13 +787,13 @@ test "add sub" {
|
||||
\\ sub w0, w0, w1
|
||||
\\ sub w2, w3, w4, uxtb #0
|
||||
\\ sub wsp, w5, w6, uxth #1
|
||||
\\ sub w7, wsp, w8, uxtw #0
|
||||
\\ sub wsp, wsp, w9, uxtw #2
|
||||
\\ sub w10, w10, wzr, uxtw #3
|
||||
\\ sub w7, wsp, w8, uxtw #2
|
||||
\\ sub wsp, wsp, w9, uxtx #0
|
||||
\\ sub w10, w10, wzr, uxtx #3
|
||||
\\ sub w11, w12, wzr, sxtb #4
|
||||
\\ sub wsp, w13, wzr, sxth #0
|
||||
\\ sub w14, wsp, wzr, sxtw #1
|
||||
\\ sub wsp, wsp, wzr, sxtw #2
|
||||
\\ sub wsp, wsp, wzr, sxtx #2
|
||||
\\
|
||||
\\ sub x0, x0, x1
|
||||
\\ sub x2, x3, w4, uxtb #0
|
||||
@ -676,21 +856,116 @@ test "add sub" {
|
||||
\\ sub xzr, xzr, x13, asr #0x1F
|
||||
\\ sub xzr, xzr, xzr, asr #0x3f
|
||||
\\
|
||||
\\ neg w0, w0
|
||||
\\ neg w1, w2, lsl #0
|
||||
\\ neg w3, wzr, lsl #7
|
||||
\\ neg wzr, w4, lsr #14
|
||||
\\ neg wzr, wzr, asr #21
|
||||
\\ subg x0, sp, #0, #0xf
|
||||
\\ subg sp, x1, #0x3f0, #0
|
||||
\\
|
||||
\\ neg x0, x0
|
||||
\\ neg x1, x2, lsl #0
|
||||
\\ neg x3, xzr, lsl #11
|
||||
\\ neg xzr, x4, lsr #22
|
||||
\\ neg xzr, xzr, asr #33
|
||||
\\ subs w0, w0, w1
|
||||
\\ subs w2, w3, w4
|
||||
\\ subs w5, w5, w6
|
||||
\\ subs w7, wsp, w8
|
||||
\\ subs w9, wsp, w9
|
||||
\\ subs w10, w10, wzr
|
||||
\\ subs w11, w12, wzr
|
||||
\\ subs wzr, w13, wzr
|
||||
\\ subs w14, wsp, wzr
|
||||
\\ subs wzr, wsp, wzr
|
||||
\\
|
||||
\\ subs x0, x0, x1
|
||||
\\ subs x2, x3, x4
|
||||
\\ subs x5, x5, x6
|
||||
\\ subs x7, sp, x8
|
||||
\\ subs x9, sp, x9
|
||||
\\ subs x10, x10, xzr
|
||||
\\ subs x11, x12, xzr
|
||||
\\ subs xzr, x13, xzr
|
||||
\\ subs x14, sp, xzr
|
||||
\\ subs xzr, sp, xzr
|
||||
\\
|
||||
\\ subs w0, w0, w1
|
||||
\\ subs w2, w3, w4, uxtb #0
|
||||
\\ subs wzr, w5, w6, uxth #1
|
||||
\\ subs w7, wsp, w8, uxtw #2
|
||||
\\ subs w9, wsp, w9, uxtx #0
|
||||
\\ subs w10, w10, wzr, uxtx #3
|
||||
\\ subs w11, w12, wzr, sxtb #4
|
||||
\\ subs wzr, w13, wzr, sxth #0
|
||||
\\ subs w14, wsp, wzr, sxtw #1
|
||||
\\ subs wzr, wsp, wzr, sxtx #2
|
||||
\\
|
||||
\\ subs x0, x0, x1
|
||||
\\ subs x2, x3, w4, uxtb #0
|
||||
\\ subs xzr, x5, w6, uxth #1
|
||||
\\ subs x7, sp, w8, uxtw #2
|
||||
\\ subs xzr, sp, x9, uxtx #0
|
||||
\\ subs x10, x10, xzr, uxtx #3
|
||||
\\ subs x11, x12, wzr, sxtb #4
|
||||
\\ subs xzr, x13, wzr, sxth #0
|
||||
\\ subs x14, sp, wzr, sxtw #1
|
||||
\\ subs xzr, sp, xzr, sxtx #2
|
||||
\\
|
||||
\\ subs w0, w0, #0
|
||||
\\ subs w0, w1, #1, lsl #0
|
||||
\\ subs wzr, w2, #2, lsl #12
|
||||
\\ subs w3, wsp, #3, lsl #0
|
||||
\\ subs wzr, wsp, #4095, lsl #12
|
||||
\\ subs w0, w1, #0
|
||||
\\ subs w2, w3, #0, lsl #0
|
||||
\\ subs w4, wsp, #0
|
||||
\\ subs w5, wsp, #0, lsl #0
|
||||
\\ subs wzr, w6, #0
|
||||
\\ subs wzr, w7, #0, lsl #0
|
||||
\\ subs wzr, wsp, #0
|
||||
\\ subs wzr, wsp, #0, lsl #0
|
||||
\\
|
||||
\\ subs x0, x0, #0
|
||||
\\ subs x0, x1, #1, lsl #0
|
||||
\\ subs xzr, x2, #2, lsl #12
|
||||
\\ subs x3, sp, #3, lsl #0
|
||||
\\ subs xzr, sp, #4095, lsl #12
|
||||
\\ subs x0, x1, #0
|
||||
\\ subs x2, x3, #0, lsl #0
|
||||
\\ subs x4, sp, #0
|
||||
\\ subs x5, sp, #0, lsl #0
|
||||
\\ subs xzr, x6, #0
|
||||
\\ subs xzr, x7, #0, lsl #0
|
||||
\\ subs xzr, sp, #0
|
||||
\\ subs xzr, sp, #0, lsl #0
|
||||
\\
|
||||
\\ subs w0, w0, w0
|
||||
\\ subs w1, w1, w2, lsl #0
|
||||
\\ subs w3, w4, w5, lsl #1
|
||||
\\ subs w6, w6, wzr, lsl #31
|
||||
\\ subs w7, wzr, w8, lsr #0
|
||||
\\ subs w9, wzr, wzr, lsr #30
|
||||
\\ subs wzr, w10, w11, lsr #31
|
||||
\\ subs wzr, w12, wzr, asr #0x0
|
||||
\\ subs wzr, wzr, w13, asr #0x10
|
||||
\\ subs wzr, wzr, wzr, asr #0x1f
|
||||
\\
|
||||
\\ subs x0, x0, x0
|
||||
\\ subs x1, x1, x2, lsl #0
|
||||
\\ subs x3, x4, x5, lsl #1
|
||||
\\ subs x6, x6, xzr, lsl #63
|
||||
\\ subs x7, xzr, x8, lsr #0
|
||||
\\ subs x9, xzr, xzr, lsr #62
|
||||
\\ subs xzr, x10, x11, lsr #63
|
||||
\\ subs xzr, x12, xzr, asr #0x0
|
||||
\\ subs xzr, xzr, x13, asr #0x1F
|
||||
\\ subs xzr, xzr, xzr, asr #0x3f
|
||||
,
|
||||
.operands = .empty,
|
||||
};
|
||||
|
||||
try std.testing.expectFmt("adc w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adc w2, w3, w4", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adc w5, w5, wzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adc w6, w7, wzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("adcs w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adcs w2, w3, w4", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adcs w5, w5, wzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adcs w6, w7, wzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("add w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add w2, w3, w4", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add wsp, w5, w6", "{f}", .{(try as.nextInstruction()).?});
|
||||
@ -714,24 +989,24 @@ test "add sub" {
|
||||
try std.testing.expectFmt("add sp, sp, xzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("add w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add w2, w3, w4, uxtb #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add w2, w3, w4, uxtb", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add wsp, w5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add w7, wsp, w8", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add wsp, wsp, w9, uxtw #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add w10, w10, wzr, uxtw #3", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add w7, wsp, w8, lsl #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add wsp, wsp, w9, uxtx", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add w10, w10, wzr, uxtx #3", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add w11, w12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add wsp, w13, wzr, sxth #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add wsp, w13, wzr, sxth", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add w14, wsp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add wsp, wsp, wzr, sxtw #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add wsp, wsp, wzr, sxtx #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("add x0, x0, x1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add x2, x3, w4, uxtb #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add x2, x3, w4, uxtb", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add sp, x5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add x7, sp, w8, uxtw #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add sp, sp, x9", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add x10, x10, xzr, uxtx #3", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add x11, x12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add sp, x13, wzr, sxth #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add sp, x13, wzr, sxth", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add x14, sp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add sp, sp, xzr, sxtx #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
@ -785,6 +1060,125 @@ test "add sub" {
|
||||
try std.testing.expectFmt("add xzr, xzr, x13, asr #31", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("add xzr, xzr, xzr, asr #63", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("addg x0, sp, #0x0, #0xf", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("addg sp, x1, #0x3f0, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("adds w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w2, w3, w4", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w5, w5, w6", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w7, wsp, w8", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w9, wsp, w9", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w10, w10, wzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w11, w12, wzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn w13, wzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w14, wsp, wzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn wsp, wzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("adds x0, x0, x1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x2, x3, x4", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x5, x5, x6", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x7, sp, x8", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x9, sp, x9", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x10, x10, xzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x11, x12, xzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn x13, xzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x14, sp, xzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn sp, xzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("adds w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w2, w3, w4, uxtb", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn w5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w7, wsp, w8, lsl #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w9, wsp, w9, uxtx", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w10, w10, wzr, uxtx #3", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w11, w12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn w13, wzr, sxth", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w14, wsp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn wsp, wzr, sxtx #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("adds x0, x0, x1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x2, x3, w4, uxtb", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn x5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x7, sp, w8, uxtw #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn sp, x9", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x10, x10, xzr, uxtx #3", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x11, x12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn x13, wzr, sxth", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x14, sp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn sp, xzr, sxtx #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("adds w0, w0, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w0, w1, #0x1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds wzr, w2, #0x2, lsl #12", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w3, wsp, #0x3", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds wzr, wsp, #0xfff, lsl #12", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w0, w1, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w2, w3, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w4, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w5, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds wzr, w6, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds wzr, w7, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds wzr, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds wzr, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("adds x0, x0, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x0, x1, #0x1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds xzr, x2, #0x2, lsl #12", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x3, sp, #0x3", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds xzr, sp, #0xfff, lsl #12", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x0, x1, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x2, x3, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x4, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x5, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds xzr, x6, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds xzr, x7, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds xzr, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds xzr, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("adds w0, w0, w0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w1, w1, w2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w3, w4, w5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w6, w6, wzr, lsl #31", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w7, wzr, w8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds w9, wzr, wzr, lsr #30", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn w10, w11, lsr #31", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn w12, wzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn wzr, w13, asr #16", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn wzr, wzr, asr #31", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("adds x0, x0, x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x1, x1, x2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x3, x4, x5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x6, x6, xzr, lsl #63", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x7, xzr, x8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("adds x9, xzr, xzr, lsr #62", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn x10, x11, lsr #63", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn x12, xzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn xzr, x13, asr #31", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmn xzr, xzr, asr #63", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("neg w0, w0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("neg w1, w2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("neg w3, wzr, lsl #7", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("neg wzr, w4, lsr #14", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("neg wzr, wzr, asr #21", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("neg x0, x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("neg x1, x2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("neg x3, xzr, lsl #11", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("neg xzr, x4, lsr #22", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("neg xzr, xzr, asr #33", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("sbc w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sbc w2, w3, w4", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sbc w5, w5, wzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sbc w6, w7, wzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("sbcs w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sbcs w2, w3, w4", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sbcs w5, w5, wzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sbcs w6, w7, wzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("sub w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub w2, w3, w4", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub wsp, w5, w6", "{f}", .{(try as.nextInstruction()).?});
|
||||
@ -808,24 +1202,24 @@ test "add sub" {
|
||||
try std.testing.expectFmt("sub sp, sp, xzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("sub w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub w2, w3, w4, uxtb #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub w2, w3, w4, uxtb", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub wsp, w5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub w7, wsp, w8", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub wsp, wsp, w9, uxtw #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub w10, w10, wzr, uxtw #3", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub w7, wsp, w8, lsl #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub wsp, wsp, w9, uxtx", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub w10, w10, wzr, uxtx #3", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub w11, w12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub wsp, w13, wzr, sxth #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub wsp, w13, wzr, sxth", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub w14, wsp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub wsp, wsp, wzr, sxtw #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub wsp, wsp, wzr, sxtx #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("sub x0, x0, x1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub x2, x3, w4, uxtb #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub x2, x3, w4, uxtb", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub sp, x5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub x7, sp, w8, uxtw #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub sp, sp, x9", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub x10, x10, xzr, uxtx #3", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub x11, x12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub sp, x13, wzr, sxth #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub sp, x13, wzr, sxth", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub x14, sp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sub sp, sp, xzr, sxtx #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
@ -879,17 +1273,102 @@ test "add sub" {
|
||||
try std.testing.expectFmt("neg xzr, x13, asr #31", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("neg xzr, xzr, asr #63", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("neg w0, w0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("neg w1, w2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("neg w3, wzr, lsl #7", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("neg wzr, w4, lsr #14", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("neg wzr, wzr, asr #21", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subg x0, sp, #0x0, #0xf", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subg sp, x1, #0x3f0, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("neg x0, x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("neg x1, x2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("neg x3, xzr, lsl #11", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("neg xzr, x4, lsr #22", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("neg xzr, xzr, asr #33", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w2, w3, w4", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w5, w5, w6", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w7, wsp, w8", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w9, wsp, w9", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w10, w10, wzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w11, w12, wzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp w13, wzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w14, wsp, wzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp wsp, wzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("subs x0, x0, x1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x2, x3, x4", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x5, x5, x6", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x7, sp, x8", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x9, sp, x9", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x10, x10, xzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x11, x12, xzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp x13, xzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x14, sp, xzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp sp, xzr", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("subs w0, w0, w1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w2, w3, w4, uxtb", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp w5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w7, wsp, w8, lsl #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w9, wsp, w9, uxtx", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w10, w10, wzr, uxtx #3", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w11, w12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp w13, wzr, sxth", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w14, wsp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp wsp, wzr, sxtx #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("subs x0, x0, x1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x2, x3, w4, uxtb", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp x5, w6, uxth #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x7, sp, w8, uxtw #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp sp, x9", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x10, x10, xzr, uxtx #3", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x11, x12, wzr, sxtb #4", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp x13, wzr, sxth", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x14, sp, wzr, sxtw #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp sp, xzr, sxtx #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("subs w0, w0, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w0, w1, #0x1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs wzr, w2, #0x2, lsl #12", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w3, wsp, #0x3", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs wzr, wsp, #0xfff, lsl #12", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w0, w1, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w2, w3, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w4, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w5, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs wzr, w6, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs wzr, w7, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs wzr, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs wzr, wsp, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("subs x0, x0, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x0, x1, #0x1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs xzr, x2, #0x2, lsl #12", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x3, sp, #0x3", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs xzr, sp, #0xfff, lsl #12", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x0, x1, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x2, x3, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x4, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x5, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs xzr, x6, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs xzr, x7, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs xzr, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs xzr, sp, #0x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("subs w0, w0, w0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w1, w1, w2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w3, w4, w5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs w6, w6, wzr, lsl #31", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("negs w7, w8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("negs w9, wzr, lsr #30", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp w10, w11, lsr #31", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp w12, wzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp wzr, w13, asr #16", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp wzr, wzr, asr #31", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("subs x0, x0, x0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x1, x1, x2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x3, x4, x5, lsl #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("subs x6, x6, xzr, lsl #63", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("negs x7, x8, lsr #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("negs x9, xzr, lsr #62", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp x10, x11, lsr #63", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp x12, xzr, asr #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp xzr, x13, asr #31", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cmp xzr, xzr, asr #63", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expect(null == try as.nextInstruction());
|
||||
}
|
||||
@ -966,44 +1445,62 @@ test "bit manipulation" {
|
||||
test "bitfield" {
|
||||
var as: Assemble = .{
|
||||
.source =
|
||||
\\sbfm w0, w0, #0, #31
|
||||
\\sbfm w0, w0, #31, #0
|
||||
\\bfc w0, #1, #31
|
||||
\\bfc w1, #31, #1
|
||||
\\bfc x2, #1, #63
|
||||
\\bfc x3, #63, #1
|
||||
\\
|
||||
\\sbfm x0, x0, #0, #63
|
||||
\\sbfm x0, x0, #63, #0
|
||||
\\bfi w0, w1, #1, #31
|
||||
\\bfi w2, wzr, #31, #1
|
||||
\\bfi x3, xzr, #1, #63
|
||||
\\bfi x4, x5, #63, #1
|
||||
\\
|
||||
\\bfm w0, w0, #0, #31
|
||||
\\bfm w0, w0, #31, #0
|
||||
\\bfm w0, wzr, #25, #5
|
||||
\\bfm w1, w2, #31, #1
|
||||
\\bfm w3, w4, #1, #31
|
||||
\\bfm x5, xzr, #57, #7
|
||||
\\bfm x6, x7, #63, #1
|
||||
\\bfm x8, x9, #1, #63
|
||||
\\
|
||||
\\bfm x0, x0, #0, #63
|
||||
\\bfm x0, x0, #63, #0
|
||||
\\sbfm w0, w1, #31, #1
|
||||
\\sbfm w2, w3, #1, #31
|
||||
\\sbfm x4, x5, #63, #1
|
||||
\\sbfm x6, x7, #1, #63
|
||||
\\
|
||||
\\ubfm w0, w0, #0, #31
|
||||
\\ubfm w0, w0, #31, #0
|
||||
\\
|
||||
\\ubfm x0, x0, #0, #63
|
||||
\\ubfm x0, x0, #63, #0
|
||||
\\ubfm w0, w1, #31, #1
|
||||
\\ubfm w2, w3, #1, #31
|
||||
\\ubfm x4, x5, #63, #1
|
||||
\\ubfm x6, x7, #1, #63
|
||||
,
|
||||
.operands = .empty,
|
||||
};
|
||||
|
||||
try std.testing.expectFmt("sbfm w0, w0, #0, #31", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sbfm w0, w0, #31, #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("bfc w0, #1, #31", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("bfc w1, #31, #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("bfc x2, #1, #63", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("bfc x3, #63, #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("sbfm x0, x0, #0, #63", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sbfm x0, x0, #63, #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("bfi w0, w1, #1, #31", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("bfc w2, #31, #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("bfc x3, #1, #63", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("bfi x4, x5, #63, #1", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("bfm w0, w0, #0, #31", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("bfm w0, w0, #31, #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("bfc w0, #7, #6", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("bfi w1, w2, #1, #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("bfxil w3, w4, #1, #31", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("bfc x5, #7, #8", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("bfi x6, x7, #1, #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("bfxil x8, x9, #1, #63", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("bfm x0, x0, #0, #63", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("bfm x0, x0, #63, #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sbfiz w0, w1, #1, #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sbfx w2, w3, #1, #31", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sbfiz x4, x5, #1, #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("sbfx x6, x7, #1, #63", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("ubfm w0, w0, #0, #31", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("ubfm w0, w0, #31, #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expectFmt("ubfm x0, x0, #0, #63", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("ubfm x0, x0, #63, #0", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("ubfiz w0, w1, #1, #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("ubfx w2, w3, #1, #31", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("ubfiz x4, x5, #1, #2", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("ubfx x6, x7, #1, #63", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expect(null == try as.nextInstruction());
|
||||
}
|
||||
@ -1113,6 +1610,22 @@ test "extract" {
|
||||
|
||||
try std.testing.expect(null == try as.nextInstruction());
|
||||
}
|
||||
test "flags" {
|
||||
var as: Assemble = .{
|
||||
.source =
|
||||
\\AXFLAG
|
||||
\\CFINV
|
||||
\\XAFLAG
|
||||
,
|
||||
.operands = .empty,
|
||||
};
|
||||
|
||||
try std.testing.expectFmt("axflag", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("cfinv", "{f}", .{(try as.nextInstruction()).?});
|
||||
try std.testing.expectFmt("xaflag", "{f}", .{(try as.nextInstruction()).?});
|
||||
|
||||
try std.testing.expect(null == try as.nextInstruction());
|
||||
}
|
||||
test "hints" {
|
||||
var as: Assemble = .{
|
||||
.source =
|
||||
@ -2935,6 +3448,5 @@ const aarch64 = @import("../aarch64.zig");
|
||||
const Assemble = @This();
|
||||
const assert = std.debug.assert;
|
||||
const Instruction = aarch64.encoding.Instruction;
|
||||
const instructions = @import("instructions.zon");
|
||||
const std = @import("std");
|
||||
const log = std.log.scoped(.@"asm");
|
||||
|
||||
@ -80,7 +80,22 @@ pub fn printInstruction(dis: Disassemble, inst: aarch64.encoding.Instruction, wr
|
||||
@tagName(sh),
|
||||
});
|
||||
},
|
||||
.add_subtract_immediate_with_tags => {},
|
||||
.add_subtract_immediate_with_tags => |add_subtract_immediate_with_tags| {
|
||||
const decoded = add_subtract_immediate_with_tags.decode();
|
||||
if (decoded == .unallocated) break :unallocated;
|
||||
const group = add_subtract_immediate_with_tags.group;
|
||||
return writer.print("{f}{s}{f}{s}{f}{s}#0x{x}{s}#0x{x}", .{
|
||||
fmtCase(decoded, dis.case),
|
||||
dis.mnemonic_operands_separator,
|
||||
group.Rd.decode(.{ .sp = true }).x().fmtCase(dis.case),
|
||||
dis.operands_separator,
|
||||
group.Rn.decode(.{ .sp = true }).x().fmtCase(dis.case),
|
||||
dis.operands_separator,
|
||||
@as(u10, group.uimm6) << 4,
|
||||
dis.operands_separator,
|
||||
group.uimm4,
|
||||
});
|
||||
},
|
||||
.logical_immediate => |logical_immediate| {
|
||||
const decoded = logical_immediate.decode();
|
||||
if (decoded == .unallocated) break :unallocated;
|
||||
@ -172,17 +187,69 @@ pub fn printInstruction(dis: Disassemble, inst: aarch64.encoding.Instruction, wr
|
||||
if (decoded == .unallocated) break :unallocated;
|
||||
const group = bitfield.group;
|
||||
const sf = group.sf;
|
||||
return writer.print("{f}{s}{f}{s}{f}{s}#{d}{s}#{d}", .{
|
||||
const Rd = group.Rd.decode(.{}).general(sf);
|
||||
const Rn = group.Rn.decode(.{}).general(sf);
|
||||
return if (!dis.enable_aliases) writer.print("{f}{s}{f}{s}{f}{s}#{d}{s}#{d}", .{
|
||||
fmtCase(decoded, dis.case),
|
||||
dis.mnemonic_operands_separator,
|
||||
group.Rd.decode(.{}).general(sf).fmtCase(dis.case),
|
||||
Rd.fmtCase(dis.case),
|
||||
dis.operands_separator,
|
||||
group.Rn.decode(.{}).general(sf).fmtCase(dis.case),
|
||||
Rn.fmtCase(dis.case),
|
||||
dis.operands_separator,
|
||||
group.imm.immr,
|
||||
dis.operands_separator,
|
||||
group.imm.imms,
|
||||
});
|
||||
}) else if (group.imm.imms >= group.imm.immr) writer.print("{f}{s}{f}{s}{f}{s}#{d}{s}#{d}", .{
|
||||
fmtCase(@as(enum { sbfx, bfxil, ubfx }, switch (decoded) {
|
||||
.unallocated => unreachable,
|
||||
.sbfm => .sbfx,
|
||||
.bfm => .bfxil,
|
||||
.ubfm => .ubfx,
|
||||
}), dis.case),
|
||||
dis.mnemonic_operands_separator,
|
||||
Rd.fmtCase(dis.case),
|
||||
dis.operands_separator,
|
||||
Rn.fmtCase(dis.case),
|
||||
dis.operands_separator,
|
||||
group.imm.immr,
|
||||
dis.operands_separator,
|
||||
switch (sf) {
|
||||
.word => @as(u6, group.imm.imms - group.imm.immr) + 1,
|
||||
.doubleword => @as(u7, group.imm.imms - group.imm.immr) + 1,
|
||||
},
|
||||
}) else {
|
||||
const prefer_bfc = switch (decoded) {
|
||||
.unallocated => unreachable,
|
||||
.sbfm, .ubfm => false,
|
||||
.bfm => Rn.alias == .zr,
|
||||
};
|
||||
try writer.print("{f}{s}{f}", .{
|
||||
fmtCase(@as(enum { sbfiz, bfc, bfi, ubfiz }, switch (decoded) {
|
||||
.unallocated => unreachable,
|
||||
.sbfm => .sbfiz,
|
||||
.bfm => if (prefer_bfc) .bfc else .bfi,
|
||||
.ubfm => .ubfiz,
|
||||
}), dis.case),
|
||||
dis.mnemonic_operands_separator,
|
||||
Rd.fmtCase(dis.case),
|
||||
});
|
||||
if (!prefer_bfc) try writer.print("{s}{f}", .{
|
||||
dis.operands_separator,
|
||||
Rn.fmtCase(dis.case),
|
||||
});
|
||||
try writer.print("{s}#{d}{s}#{d}", .{
|
||||
dis.operands_separator,
|
||||
switch (sf) {
|
||||
.word => -%@as(u5, @intCast(group.imm.immr)),
|
||||
.doubleword => -%@as(u6, @intCast(group.imm.immr)),
|
||||
},
|
||||
dis.operands_separator,
|
||||
switch (sf) {
|
||||
.word => @as(u6, group.imm.imms) + 1,
|
||||
.doubleword => @as(u7, group.imm.imms) + 1,
|
||||
},
|
||||
});
|
||||
};
|
||||
},
|
||||
.extract => |extract| {
|
||||
const decoded = extract.decode();
|
||||
@ -249,7 +316,11 @@ pub fn printInstruction(dis: Disassemble, inst: aarch64.encoding.Instruction, wr
|
||||
else => |decoded| return writer.print("{f}", .{fmtCase(decoded, dis.case)}),
|
||||
},
|
||||
.barriers => {},
|
||||
.pstate => {},
|
||||
.pstate => |pstate| {
|
||||
const decoded = pstate.decode();
|
||||
if (decoded == .unallocated) break :unallocated;
|
||||
return writer.print("{f}", .{fmtCase(decoded, dis.case)});
|
||||
},
|
||||
.system_result => {},
|
||||
.system => {},
|
||||
.system_register_move => {},
|
||||
@ -695,9 +766,19 @@ pub fn printInstruction(dis: Disassemble, inst: aarch64.encoding.Instruction, wr
|
||||
if (decoded == .unallocated) break :unallocated;
|
||||
const group = add_subtract_extended_register.group;
|
||||
const sf = group.sf;
|
||||
const Rm = group.Rm.decode(.{}).general(group.option.sf());
|
||||
const Rm = group.Rm.decode(.{}).general(switch (sf) {
|
||||
.word => .word,
|
||||
.doubleword => group.option.sf(),
|
||||
});
|
||||
const Rn = group.Rn.decode(.{ .sp = true }).general(sf);
|
||||
const Rd = group.Rd.decode(.{ .sp = true }).general(sf);
|
||||
const Rd = group.Rd.decode(.{ .sp = !group.S }).general(sf);
|
||||
const prefer_lsl = (Rd.alias == .sp or Rn.alias == .sp) and group.option == @as(
|
||||
aarch64.encoding.Instruction.DataProcessingRegister.AddSubtractExtendedRegister.Option,
|
||||
switch (sf) {
|
||||
.word => .uxtw,
|
||||
.doubleword => .uxtx,
|
||||
},
|
||||
);
|
||||
if (dis.enable_aliases and group.S and Rd.alias == .zr) try writer.print("{f}{s}{f}{s}{f}", .{
|
||||
fmtCase(@as(enum { cmn, cmp }, switch (group.op) {
|
||||
.add => .cmn,
|
||||
@ -716,14 +797,13 @@ pub fn printInstruction(dis: Disassemble, inst: aarch64.encoding.Instruction, wr
|
||||
dis.operands_separator,
|
||||
Rm.fmtCase(dis.case),
|
||||
});
|
||||
return if (group.option != @as(aarch64.encoding.Instruction.DataProcessingRegister.AddSubtractExtendedRegister.Option, switch (sf) {
|
||||
.word => .uxtw,
|
||||
.doubleword => .uxtx,
|
||||
}) or group.imm3 != 0) writer.print("{s}{f} #{d}", .{
|
||||
dis.operands_separator,
|
||||
fmtCase(group.option, dis.case),
|
||||
group.imm3,
|
||||
});
|
||||
return if (!prefer_lsl or group.imm3 != 0) {
|
||||
try writer.print("{s}{f}", .{
|
||||
dis.operands_separator,
|
||||
if (prefer_lsl) fmtCase(.lsl, dis.case) else fmtCase(group.option, dis.case),
|
||||
});
|
||||
if (group.imm3 != 0) try writer.print(" #{d}", .{group.imm3});
|
||||
};
|
||||
},
|
||||
.add_subtract_with_carry => |add_subtract_with_carry| {
|
||||
const decoded = add_subtract_with_carry.decode();
|
||||
|
||||
@ -2563,6 +2563,10 @@ pub const Instruction = packed union {
|
||||
/// PSTATE
|
||||
pub const Pstate = packed union {
|
||||
group: @This().Group,
|
||||
msr: Msr,
|
||||
cfinv: Cfinv,
|
||||
xaflag: Xaflag,
|
||||
axflag: Axflag,
|
||||
|
||||
pub const Group = packed struct {
|
||||
Rt: Register.Encoded,
|
||||
@ -2615,6 +2619,7 @@ pub const Instruction = packed union {
|
||||
|
||||
pub const Decoded = union(enum) {
|
||||
unallocated,
|
||||
msr: Msr,
|
||||
cfinv: Cfinv,
|
||||
xaflag: Xaflag,
|
||||
axflag: Axflag,
|
||||
@ -11414,7 +11419,10 @@ pub const Instruction = packed union {
|
||||
assert(n.format.general == sf);
|
||||
form: switch (form) {
|
||||
.extended_register_explicit => |extended_register_explicit| {
|
||||
assert(extended_register_explicit.register.format.general == extended_register_explicit.option.sf());
|
||||
assert(extended_register_explicit.register.format.general == switch (sf) {
|
||||
.word => .word,
|
||||
.doubleword => extended_register_explicit.option.sf(),
|
||||
});
|
||||
return .{ .data_processing_register = .{ .add_subtract_extended_register = .{
|
||||
.add = .{
|
||||
.Rd = d.alias.encode(.{ .sp = true }),
|
||||
@ -11484,6 +11492,18 @@ pub const Instruction = packed union {
|
||||
} },
|
||||
}
|
||||
}
|
||||
/// C7.2.6 ADDG
|
||||
pub fn addg(d: Register, n: Register, uimm6: u10, uimm4: u4) Instruction {
|
||||
assert(d.format.general == .doubleword and n.format.general == .doubleword);
|
||||
return .{ .data_processing_immediate = .{ .add_subtract_immediate_with_tags = .{
|
||||
.addg = .{
|
||||
.Xd = d.alias.encode(.{ .sp = true }),
|
||||
.Xn = n.alias.encode(.{ .sp = true }),
|
||||
.uimm4 = uimm4,
|
||||
.uimm6 = @intCast(@shrExact(uimm6, 4)),
|
||||
},
|
||||
} } };
|
||||
}
|
||||
/// C7.2.4 ADDP (scalar)
|
||||
/// C7.2.5 ADDP (vector)
|
||||
pub fn addp(d: Register, n: Register, form: union(enum) {
|
||||
@ -11536,7 +11556,10 @@ pub const Instruction = packed union {
|
||||
assert(n.format.general == sf);
|
||||
form: switch (form) {
|
||||
.extended_register_explicit => |extended_register_explicit| {
|
||||
assert(extended_register_explicit.register.format.general == extended_register_explicit.option.sf());
|
||||
assert(extended_register_explicit.register.format.general == switch (sf) {
|
||||
.word => .word,
|
||||
.doubleword => extended_register_explicit.option.sf(),
|
||||
});
|
||||
return .{ .data_processing_register = .{ .add_subtract_extended_register = .{
|
||||
.adds = .{
|
||||
.Rd = d.alias.encode(.{}),
|
||||
@ -11768,6 +11791,12 @@ pub const Instruction = packed union {
|
||||
},
|
||||
} } };
|
||||
}
|
||||
/// C6.2.24 AXFLAG
|
||||
pub fn axflag() Instruction {
|
||||
return .{ .branch_exception_generating_system = .{ .pstate = .{
|
||||
.axflag = .{},
|
||||
} } };
|
||||
}
|
||||
/// C6.2.25 B
|
||||
pub fn b(label: i28) Instruction {
|
||||
return .{ .branch_exception_generating_system = .{ .unconditional_branch_immediate = .{
|
||||
@ -12066,6 +12095,12 @@ pub const Instruction = packed union {
|
||||
} } },
|
||||
}
|
||||
}
|
||||
/// C6.2.52 CFINV
|
||||
pub fn cfinv() Instruction {
|
||||
return .{ .branch_exception_generating_system = .{ .pstate = .{
|
||||
.cfinv = .{},
|
||||
} } };
|
||||
}
|
||||
/// C6.2.56 CLREX
|
||||
pub fn clrex(imm: u4) Instruction {
|
||||
return .{ .branch_exception_generating_system = .{ .barriers = .{
|
||||
@ -16057,7 +16092,10 @@ pub const Instruction = packed union {
|
||||
assert(n.format.general == sf);
|
||||
form: switch (form) {
|
||||
.extended_register_explicit => |extended_register_explicit| {
|
||||
assert(extended_register_explicit.register.format.general == extended_register_explicit.option.sf());
|
||||
assert(extended_register_explicit.register.format.general == switch (sf) {
|
||||
.word => .word,
|
||||
.doubleword => extended_register_explicit.option.sf(),
|
||||
});
|
||||
return .{ .data_processing_register = .{ .add_subtract_extended_register = .{
|
||||
.sub = .{
|
||||
.Rd = d.alias.encode(.{ .sp = true }),
|
||||
@ -16127,6 +16165,18 @@ pub const Instruction = packed union {
|
||||
} },
|
||||
}
|
||||
}
|
||||
/// C7.2.359 SUBG
|
||||
pub fn subg(d: Register, n: Register, uimm6: u10, uimm4: u4) Instruction {
|
||||
assert(d.format.general == .doubleword and n.format.general == .doubleword);
|
||||
return .{ .data_processing_immediate = .{ .add_subtract_immediate_with_tags = .{
|
||||
.subg = .{
|
||||
.Xd = d.alias.encode(.{ .sp = true }),
|
||||
.Xn = n.alias.encode(.{ .sp = true }),
|
||||
.uimm4 = uimm4,
|
||||
.uimm6 = @intCast(@shrExact(uimm6, 4)),
|
||||
},
|
||||
} } };
|
||||
}
|
||||
/// C6.2.362 SUBS (extended register)
|
||||
/// C6.2.363 SUBS (immediate)
|
||||
/// C6.2.364 SUBS (shifted register)
|
||||
@ -16147,7 +16197,10 @@ pub const Instruction = packed union {
|
||||
assert(n.format.general == sf);
|
||||
form: switch (form) {
|
||||
.extended_register_explicit => |extended_register_explicit| {
|
||||
assert(extended_register_explicit.register.format.general == extended_register_explicit.option.sf());
|
||||
assert(extended_register_explicit.register.format.general == switch (sf) {
|
||||
.word => .word,
|
||||
.doubleword => extended_register_explicit.option.sf(),
|
||||
});
|
||||
return .{ .data_processing_register = .{ .add_subtract_extended_register = .{
|
||||
.subs = .{
|
||||
.Rd = d.alias.encode(.{}),
|
||||
@ -16471,6 +16524,12 @@ pub const Instruction = packed union {
|
||||
.wfi = .{},
|
||||
} } };
|
||||
}
|
||||
/// C6.2.400 XAFLAG
|
||||
pub fn xaflag() Instruction {
|
||||
return .{ .branch_exception_generating_system = .{ .pstate = .{
|
||||
.xaflag = .{},
|
||||
} } };
|
||||
}
|
||||
/// C6.2.402 YIELD
|
||||
pub fn yield() Instruction {
|
||||
return .{ .branch_exception_generating_system = .{ .hints = .{
|
||||
|
||||
@ -1,4 +1,42 @@
|
||||
.{
|
||||
// C6.2.1 ADC
|
||||
.{
|
||||
.pattern = "ADC <Wd>, <Wn>, <Wm>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
},
|
||||
.encode = .{ .adc, .Wd, .Wn, .Wm },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADC <Xd>, <Xn>, <Xm>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
},
|
||||
.encode = .{ .adc, .Xd, .Xn, .Xm },
|
||||
},
|
||||
// C6.2.2 ADCS
|
||||
.{
|
||||
.pattern = "ADCS <Wd>, <Wn>, <Wm>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
},
|
||||
.encode = .{ .adcs, .Wd, .Wn, .Wm },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADCS <Xd>, <Xn>, <Xm>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
},
|
||||
.encode = .{ .adcs, .Xd, .Xn, .Xm },
|
||||
},
|
||||
// C6.2.3 ADD (extended register)
|
||||
.{
|
||||
.pattern = "ADD <Wd|WSP>, <Wn|WSP>, <Wm>",
|
||||
@ -9,13 +47,27 @@
|
||||
},
|
||||
.encode = .{ .add, .Wd, .Wn, .{ .register = .Wm } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADD <Wd|WSP>, <Wn|WSP>, <Wm>, <extend>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.extend = .{ .extend = .{} },
|
||||
},
|
||||
.encode = .{ .add, .Wd, .Wn, .{ .extended_register_explicit = .{
|
||||
.register = .Wm,
|
||||
.option = .extend,
|
||||
.amount = 0,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADD <Wd|WSP>, <Wn|WSP>, <Wm>, <extend> #<amount>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.extend = .{ .extend = .{ .size = .word } },
|
||||
.extend = .{ .extend = .{} },
|
||||
.amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
|
||||
},
|
||||
.encode = .{ .add, .Wd, .Wn, .{ .extended_register_explicit = .{
|
||||
@ -33,6 +85,20 @@
|
||||
},
|
||||
.encode = .{ .add, .Xd, .Xn, .{ .register = .Xm } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADD <Xd|SP>, <Xn|SP>, <Wm>, <extend>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.extend = .{ .extend = .{ .size = .word } },
|
||||
},
|
||||
.encode = .{ .add, .Xd, .Xn, .{ .extended_register_explicit = .{
|
||||
.register = .Wm,
|
||||
.option = .extend,
|
||||
.amount = 0,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADD <Xd|SP>, <Xn|SP>, <Wm>, <extend> #<amount>",
|
||||
.symbols = .{
|
||||
@ -48,6 +114,20 @@
|
||||
.amount = .amount,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADD <Xd|SP>, <Xn|SP>, <Xm>, <extend>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.extend = .{ .extend = .{ .size = .doubleword } },
|
||||
},
|
||||
.encode = .{ .add, .Xd, .Xn, .{ .extended_register_explicit = .{
|
||||
.register = .Xm,
|
||||
.option = .extend,
|
||||
.amount = 0,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADD <Xd|SP>, <Xn|SP>, <Xm>, <extend> #<amount>",
|
||||
.symbols = .{
|
||||
@ -151,6 +231,212 @@
|
||||
.amount = .amount,
|
||||
} } },
|
||||
},
|
||||
// C6.2.6 ADDG
|
||||
.{
|
||||
.requires = .{.mte},
|
||||
.pattern = "ADDG <Xd|SP>, <Xn|SP>, #<uimm6>, #<uimm4>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.uimm6 = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 10 }, .multiple_of = 16 } },
|
||||
.uimm4 = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 } } },
|
||||
},
|
||||
.encode = .{ .addg, .Xd, .Xn, .uimm6, .uimm4 },
|
||||
},
|
||||
// C6.2.7 ADDS (extended register)
|
||||
.{
|
||||
.pattern = "ADDS <Wd>, <Wn|WSP>, <Wm>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
},
|
||||
.encode = .{ .adds, .Wd, .Wn, .{ .register = .Wm } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADDS <Wd>, <Wn|WSP>, <Wm>, <extend>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.extend = .{ .extend = .{} },
|
||||
},
|
||||
.encode = .{ .adds, .Wd, .Wn, .{ .extended_register_explicit = .{
|
||||
.register = .Wm,
|
||||
.option = .extend,
|
||||
.amount = 0,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADDS <Wd>, <Wn|WSP>, <Wm>, <extend> #<amount>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.extend = .{ .extend = .{} },
|
||||
.amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
|
||||
},
|
||||
.encode = .{ .adds, .Wd, .Wn, .{ .extended_register_explicit = .{
|
||||
.register = .Wm,
|
||||
.option = .extend,
|
||||
.amount = .amount,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADDS <Xd>, <Xn|SP>, <Xm>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
},
|
||||
.encode = .{ .adds, .Xd, .Xn, .{ .register = .Xm } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADDS <Xd>, <Xn|SP>, <Wm>, <extend>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.extend = .{ .extend = .{ .size = .word } },
|
||||
},
|
||||
.encode = .{ .adds, .Xd, .Xn, .{ .extended_register_explicit = .{
|
||||
.register = .Wm,
|
||||
.option = .extend,
|
||||
.amount = 0,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADDS <Xd>, <Xn|SP>, <Wm>, <extend> #<amount>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.extend = .{ .extend = .{ .size = .word } },
|
||||
.amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
|
||||
},
|
||||
.encode = .{ .adds, .Xd, .Xn, .{ .extended_register_explicit = .{
|
||||
.register = .Wm,
|
||||
.option = .extend,
|
||||
.amount = .amount,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADDS <Xd>, <Xn|SP>, <Xm>, <extend>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.extend = .{ .extend = .{ .size = .doubleword } },
|
||||
},
|
||||
.encode = .{ .adds, .Xd, .Xn, .{ .extended_register_explicit = .{
|
||||
.register = .Xm,
|
||||
.option = .extend,
|
||||
.amount = 0,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADDS <Xd>, <Xn|SP>, <Xm>, <extend> #<amount>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.extend = .{ .extend = .{ .size = .doubleword } },
|
||||
.amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
|
||||
},
|
||||
.encode = .{ .adds, .Xd, .Xn, .{ .extended_register_explicit = .{
|
||||
.register = .Xm,
|
||||
.option = .extend,
|
||||
.amount = .amount,
|
||||
} } },
|
||||
},
|
||||
// C6.2.8 ADDS (immediate)
|
||||
.{
|
||||
.pattern = "ADDS <Wd>, <Wn|WSP>, #<imm>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
|
||||
.imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
|
||||
},
|
||||
.encode = .{ .adds, .Wd, .Wn, .{ .immediate = .imm } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADDS <Wd>, <Wn|WSP>, #<imm>, LSL #<shift>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
|
||||
.imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
|
||||
.shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 }, .multiple_of = 12 } },
|
||||
},
|
||||
.encode = .{ .adds, .Wd, .Wn, .{ .shifted_immediate = .{ .immediate = .imm, .lsl = .shift } } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADDS <Xd>, <Xn|SP>, #<imm>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
|
||||
},
|
||||
.encode = .{ .adds, .Xd, .Xn, .{ .immediate = .imm } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADDS <Xd>, <Xn|SP>, #<imm>, LSL #<shift>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
|
||||
.shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 }, .multiple_of = 12 } },
|
||||
},
|
||||
.encode = .{ .adds, .Xd, .Xn, .{ .shifted_immediate = .{ .immediate = .imm, .lsl = .shift } } },
|
||||
},
|
||||
// C6.2.9 ADDS (shifted register)
|
||||
.{
|
||||
.pattern = "ADDS <Wd>, <Wn>, <Wm>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
},
|
||||
.encode = .{ .adds, .Wd, .Wn, .{ .register = .Wm } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADDS <Wd>, <Wn>, <Wm>, <shift> #<amount>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.shift = .{ .shift = .{ .allow_ror = false } },
|
||||
.amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
|
||||
},
|
||||
.encode = .{ .adds, .Wd, .Wn, .{ .shifted_register_explicit = .{
|
||||
.register = .Wm,
|
||||
.shift = .shift,
|
||||
.amount = .amount,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADDS <Xd>, <Xn>, <Xm>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
},
|
||||
.encode = .{ .adds, .Xd, .Xn, .{ .register = .Xm } },
|
||||
},
|
||||
.{
|
||||
.pattern = "ADDS <Xd>, <Xn>, <Xm>, <shift> #<amount>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.shift = .{ .shift = .{ .allow_ror = false } },
|
||||
.amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
|
||||
},
|
||||
.encode = .{ .adds, .Xd, .Xn, .{ .shifted_register_explicit = .{
|
||||
.register = .Xm,
|
||||
.shift = .shift,
|
||||
.amount = .amount,
|
||||
} } },
|
||||
},
|
||||
// C6.2.13 AND (shifted register)
|
||||
.{
|
||||
.pattern = "AND <Wd>, <Wn>, <Wm>",
|
||||
@ -306,6 +592,53 @@
|
||||
},
|
||||
.encode = .{ .asrv, .Xd, .Xn, .Xm },
|
||||
},
|
||||
// C6.2.24 AXFLAG
|
||||
.{
|
||||
.requires = .{.altnzcv},
|
||||
.pattern = "AXFLAG",
|
||||
.symbols = .{},
|
||||
.encode = .{.axflag},
|
||||
},
|
||||
// C6.2.28 BFC
|
||||
.{
|
||||
.pattern = "BFC <Wd>, #<lsb>, #<width>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.lsb = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 }, .adjust = .neg_wrap } },
|
||||
.width = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 }, .adjust = .dec } },
|
||||
},
|
||||
.encode = .{ .bfm, .Wd, .wzr, .{ .N = .word, .immr = .lsb, .imms = .width } },
|
||||
},
|
||||
.{
|
||||
.pattern = "BFC <Xd>, #<lsb>, #<width>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.lsb = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 }, .adjust = .neg_wrap } },
|
||||
.width = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 }, .adjust = .dec } },
|
||||
},
|
||||
.encode = .{ .bfm, .Xd, .xzr, .{ .N = .doubleword, .immr = .lsb, .imms = .width } },
|
||||
},
|
||||
// C6.2.29 BFI
|
||||
.{
|
||||
.pattern = "BFI <Wd>, <Wn>, #<lsb>, #<width>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.lsb = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 }, .adjust = .neg_wrap } },
|
||||
.width = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 }, .adjust = .dec } },
|
||||
},
|
||||
.encode = .{ .bfm, .Wd, .Wn, .{ .N = .word, .immr = .lsb, .imms = .width } },
|
||||
},
|
||||
.{
|
||||
.pattern = "BFI <Xd>, <Xn>, #<lsb>, #<width>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.lsb = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 }, .adjust = .neg_wrap } },
|
||||
.width = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 }, .adjust = .dec } },
|
||||
},
|
||||
.encode = .{ .bfm, .Xd, .Xn, .{ .N = .doubleword, .immr = .lsb, .imms = .width } },
|
||||
},
|
||||
// C6.2.30 BFM
|
||||
.{
|
||||
.pattern = "BFM <Wd>, <Wn>, #<immr>, #<imms>",
|
||||
@ -351,6 +684,13 @@
|
||||
},
|
||||
.encode = .{ .brk, .imm },
|
||||
},
|
||||
// C6.2.52 CFINV
|
||||
.{
|
||||
.requires = .{.flagm},
|
||||
.pattern = "CFINV",
|
||||
.symbols = .{},
|
||||
.encode = .{.cfinv},
|
||||
},
|
||||
// C6.2.56 CLREX
|
||||
.{
|
||||
.pattern = "CLREX",
|
||||
@ -1391,6 +1731,44 @@
|
||||
},
|
||||
.encode = .{ .rorv, .Xd, .Xn, .Xm },
|
||||
},
|
||||
// C6.2.265 SBC
|
||||
.{
|
||||
.pattern = "SBC <Wd>, <Wn>, <Wm>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
},
|
||||
.encode = .{ .sbc, .Wd, .Wn, .Wm },
|
||||
},
|
||||
.{
|
||||
.pattern = "SBC <Xd>, <Xn>, <Xm>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
},
|
||||
.encode = .{ .sbc, .Xd, .Xn, .Xm },
|
||||
},
|
||||
// C6.2.266 SBCS
|
||||
.{
|
||||
.pattern = "SBCS <Wd>, <Wn>, <Wm>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
},
|
||||
.encode = .{ .sbcs, .Wd, .Wn, .Wm },
|
||||
},
|
||||
.{
|
||||
.pattern = "SBCS <Xd>, <Xn>, <Xm>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
},
|
||||
.encode = .{ .sbcs, .Xd, .Xn, .Xm },
|
||||
},
|
||||
// C6.2.268 SBFM
|
||||
.{
|
||||
.pattern = "SBFM <Wd>, <Wn>, #<immr>, #<imms>",
|
||||
@ -1663,13 +2041,27 @@
|
||||
},
|
||||
.encode = .{ .sub, .Wd, .Wn, .{ .register = .Wm } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUB <Wd|WSP>, <Wn|WSP>, <Wm>, <extend>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.extend = .{ .extend = .{} },
|
||||
},
|
||||
.encode = .{ .sub, .Wd, .Wn, .{ .extended_register_explicit = .{
|
||||
.register = .Wm,
|
||||
.option = .extend,
|
||||
.amount = 0,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUB <Wd|WSP>, <Wn|WSP>, <Wm>, <extend> #<amount>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.extend = .{ .extend = .{ .size = .word } },
|
||||
.extend = .{ .extend = .{} },
|
||||
.amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
|
||||
},
|
||||
.encode = .{ .sub, .Wd, .Wn, .{ .extended_register_explicit = .{
|
||||
@ -1687,6 +2079,20 @@
|
||||
},
|
||||
.encode = .{ .sub, .Xd, .Xn, .{ .register = .Xm } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUB <Xd|SP>, <Xn|SP>, <Wm>, <extend>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.extend = .{ .extend = .{ .size = .word } },
|
||||
},
|
||||
.encode = .{ .sub, .Xd, .Xn, .{ .extended_register_explicit = .{
|
||||
.register = .Wm,
|
||||
.option = .extend,
|
||||
.amount = 0,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUB <Xd|SP>, <Xn|SP>, <Wm>, <extend> #<amount>",
|
||||
.symbols = .{
|
||||
@ -1702,6 +2108,20 @@
|
||||
.amount = .amount,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUB <Xd|SP>, <Xn|SP>, <Xm>, <extend>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.extend = .{ .extend = .{ .size = .doubleword } },
|
||||
},
|
||||
.encode = .{ .sub, .Xd, .Xn, .{ .extended_register_explicit = .{
|
||||
.register = .Xm,
|
||||
.option = .extend,
|
||||
.amount = 0,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUB <Xd|SP>, <Xn|SP>, <Xm>, <extend> #<amount>",
|
||||
.symbols = .{
|
||||
@ -1805,6 +2225,212 @@
|
||||
.amount = .amount,
|
||||
} } },
|
||||
},
|
||||
// C6.2.359 SUBG
|
||||
.{
|
||||
.requires = .{.mte},
|
||||
.pattern = "SUBG <Xd|SP>, <Xn|SP>, #<uimm6>, #<uimm4>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.uimm6 = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 10 }, .multiple_of = 16 } },
|
||||
.uimm4 = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 } } },
|
||||
},
|
||||
.encode = .{ .subg, .Xd, .Xn, .uimm6, .uimm4 },
|
||||
},
|
||||
// C6.2.362 SUBS (extended register)
|
||||
.{
|
||||
.pattern = "SUBS <Wd>, <Wn|WSP>, <Wm>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
},
|
||||
.encode = .{ .subs, .Wd, .Wn, .{ .register = .Wm } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUBS <Wd>, <Wn|WSP>, <Wm>, <extend>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.extend = .{ .extend = .{} },
|
||||
},
|
||||
.encode = .{ .subs, .Wd, .Wn, .{ .extended_register_explicit = .{
|
||||
.register = .Wm,
|
||||
.option = .extend,
|
||||
.amount = 0,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUBS <Wd>, <Wn|WSP>, <Wm>, <extend> #<amount>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.extend = .{ .extend = .{} },
|
||||
.amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
|
||||
},
|
||||
.encode = .{ .subs, .Wd, .Wn, .{ .extended_register_explicit = .{
|
||||
.register = .Wm,
|
||||
.option = .extend,
|
||||
.amount = .amount,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUBS <Xd>, <Xn|SP>, <Xm>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
},
|
||||
.encode = .{ .subs, .Xd, .Xn, .{ .register = .Xm } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUBS <Xd>, <Xn|SP>, <Wm>, <extend>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.extend = .{ .extend = .{ .size = .word } },
|
||||
},
|
||||
.encode = .{ .subs, .Xd, .Xn, .{ .extended_register_explicit = .{
|
||||
.register = .Wm,
|
||||
.option = .extend,
|
||||
.amount = 0,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUBS <Xd>, <Xn|SP>, <Wm>, <extend> #<amount>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.extend = .{ .extend = .{ .size = .word } },
|
||||
.amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
|
||||
},
|
||||
.encode = .{ .subs, .Xd, .Xn, .{ .extended_register_explicit = .{
|
||||
.register = .Wm,
|
||||
.option = .extend,
|
||||
.amount = .amount,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUBS <Xd>, <Xn|SP>, <Xm>, <extend>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.extend = .{ .extend = .{ .size = .doubleword } },
|
||||
},
|
||||
.encode = .{ .subs, .Xd, .Xn, .{ .extended_register_explicit = .{
|
||||
.register = .Xm,
|
||||
.option = .extend,
|
||||
.amount = 0,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUBS <Xd>, <Xn|SP>, <Xm>, <extend> #<amount>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.extend = .{ .extend = .{ .size = .doubleword } },
|
||||
.amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 3 }, .max_valid = 4 } },
|
||||
},
|
||||
.encode = .{ .subs, .Xd, .Xn, .{ .extended_register_explicit = .{
|
||||
.register = .Xm,
|
||||
.option = .extend,
|
||||
.amount = .amount,
|
||||
} } },
|
||||
},
|
||||
// C6.2.363 SUBS (immediate)
|
||||
.{
|
||||
.pattern = "SUBS <Wd>, <Wn|WSP>, #<imm>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
|
||||
.imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
|
||||
},
|
||||
.encode = .{ .subs, .Wd, .Wn, .{ .immediate = .imm } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUBS <Wd>, <Wn|WSP>, #<imm>, LSL #<shift>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word }, .allow_sp = true } },
|
||||
.imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
|
||||
.shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 }, .multiple_of = 12 } },
|
||||
},
|
||||
.encode = .{ .subs, .Wd, .Wn, .{ .shifted_immediate = .{ .immediate = .imm, .lsl = .shift } } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUBS <Xd>, <Xn|SP>, #<imm>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
|
||||
},
|
||||
.encode = .{ .subs, .Xd, .Xn, .{ .immediate = .imm } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUBS <Xd>, <Xn|SP>, #<imm>, LSL #<shift>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword }, .allow_sp = true } },
|
||||
.imm = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 12 } } },
|
||||
.shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 4 }, .multiple_of = 12 } },
|
||||
},
|
||||
.encode = .{ .subs, .Xd, .Xn, .{ .shifted_immediate = .{ .immediate = .imm, .lsl = .shift } } },
|
||||
},
|
||||
// C6.2.364 SUBS (shifted register)
|
||||
.{
|
||||
.pattern = "SUBS <Wd>, <Wn>, <Wm>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
},
|
||||
.encode = .{ .subs, .Wd, .Wn, .{ .register = .Wm } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUBS <Wd>, <Wn>, <Wm>, <shift> #<amount>",
|
||||
.symbols = .{
|
||||
.Wd = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wn = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.Wm = .{ .reg = .{ .format = .{ .general = .word } } },
|
||||
.shift = .{ .shift = .{ .allow_ror = false } },
|
||||
.amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
|
||||
},
|
||||
.encode = .{ .subs, .Wd, .Wn, .{ .shifted_register_explicit = .{
|
||||
.register = .Wm,
|
||||
.shift = .shift,
|
||||
.amount = .amount,
|
||||
} } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUBS <Xd>, <Xn>, <Xm>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
},
|
||||
.encode = .{ .subs, .Xd, .Xn, .{ .register = .Xm } },
|
||||
},
|
||||
.{
|
||||
.pattern = "SUBS <Xd>, <Xn>, <Xm>, <shift> #<amount>",
|
||||
.symbols = .{
|
||||
.Xd = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xn = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.Xm = .{ .reg = .{ .format = .{ .general = .doubleword } } },
|
||||
.shift = .{ .shift = .{ .allow_ror = false } },
|
||||
.amount = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
|
||||
},
|
||||
.encode = .{ .subs, .Xd, .Xn, .{ .shifted_register_explicit = .{
|
||||
.register = .Xm,
|
||||
.shift = .shift,
|
||||
.amount = .amount,
|
||||
} } },
|
||||
},
|
||||
// C6.2.365 SVC
|
||||
.{
|
||||
.pattern = "SVC #<imm>",
|
||||
@ -1933,6 +2559,13 @@
|
||||
.symbols = .{},
|
||||
.encode = .{.wfi},
|
||||
},
|
||||
// C6.2.400 XAFLAG
|
||||
.{
|
||||
.requires = .{.altnzcv},
|
||||
.pattern = "XAFLAG",
|
||||
.symbols = .{},
|
||||
.encode = .{.xaflag},
|
||||
},
|
||||
// C6.2.402 YIELD
|
||||
.{
|
||||
.pattern = "YIELD",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user