Skip to content

Commit 94d319a

Browse files
jacobly0andrewrk
authored andcommitted
x86_64: support more in/out forms
Closes ziglang#25303
1 parent 561e556 commit 94d319a

File tree

1 file changed

+61
-46
lines changed

1 file changed

+61
-46
lines changed

src/arch/x86_64/CodeGen.zig

Lines changed: 61 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -180114,58 +180114,73 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
180114180114
}
180115180115

180116180116
var mnem_size: struct {
180117+
op_has_size: std.StaticBitSet(4),
180118+
size: Memory.Size,
180117180119
used: bool,
180118-
size: ?Memory.Size,
180119-
fn use(size: *@This()) ?Memory.Size {
180120+
fn init(size: ?Memory.Size) @This() {
180121+
return .{
180122+
.op_has_size = if (size) |_| .initFull() else .initEmpty(),
180123+
.size = size orelse .none,
180124+
.used = false,
180125+
};
180126+
}
180127+
fn use(size: *@This(), op_index: usize) ?Memory.Size {
180128+
if (!size.op_has_size.isSet(op_index)) return null;
180120180129
size.used = true;
180121180130
return size.size;
180122180131
}
180123-
} = .{
180124-
.used = false,
180125-
.size = if (prefix == .directive)
180126-
null
180127-
else if (std.mem.endsWith(u8, mnem_str, "b"))
180128-
.byte
180129-
else if (std.mem.endsWith(u8, mnem_str, "w"))
180130-
.word
180131-
else if (std.mem.endsWith(u8, mnem_str, "l"))
180132-
.dword
180133-
else if (std.mem.endsWith(u8, mnem_str, "q") and
180134-
(std.mem.indexOfScalar(u8, "vp", mnem_str[0]) == null or !std.mem.endsWith(u8, mnem_str, "dq")))
180135-
.qword
180136-
else if (std.mem.endsWith(u8, mnem_str, "t"))
180137-
.tbyte
180138-
else
180139-
null,
180140-
};
180132+
} = .init(if (prefix == .directive)
180133+
null
180134+
else if (std.mem.endsWith(u8, mnem_str, "b"))
180135+
.byte
180136+
else if (std.mem.endsWith(u8, mnem_str, "w"))
180137+
.word
180138+
else if (std.mem.endsWith(u8, mnem_str, "l"))
180139+
.dword
180140+
else if (std.mem.endsWith(u8, mnem_str, "q") and
180141+
(std.mem.indexOfScalar(u8, "vp", mnem_str[0]) == null or !std.mem.endsWith(u8, mnem_str, "dq")))
180142+
.qword
180143+
else if (std.mem.endsWith(u8, mnem_str, "t"))
180144+
.tbyte
180145+
else
180146+
null);
180141180147
var mnem_tag = while (true) break std.meta.stringToEnum(
180142180148
encoder.Instruction.Mnemonic,
180143-
mnem_str[0 .. mnem_str.len - @intFromBool(mnem_size.size != null)],
180144-
) orelse if (mnem_size.size) |_| {
180145-
mnem_size.size = null;
180149+
mnem_str[0 .. mnem_str.len - @intFromBool(mnem_size.size != .none)],
180150+
) orelse if (mnem_size.size != .none) {
180151+
mnem_size = .init(null);
180146180152
continue;
180147180153
} else return self.fail("invalid mnemonic: '{s}'", .{mnem_str});
180148-
if (@as(?Memory.Size, switch (mnem_tag) {
180149-
.clflush => .byte,
180150-
.fldcw, .fnstcw, .fstcw, .fnstsw, .fstsw => .word,
180151-
.fldenv, .fnstenv, .fstenv => .none,
180152-
.frstor, .fsave, .fnsave, .fxrstor, .fxrstor64, .fxsave, .fxsave64 => .none,
180153-
.invlpg => .none,
180154-
.invpcid => .xword,
180155-
.ldmxcsr, .stmxcsr, .vldmxcsr, .vstmxcsr => .dword,
180156-
else => null,
180157-
})) |fixed_mnem_size| {
180158-
if (mnem_size.size) |size| if (size != fixed_mnem_size)
180154+
fixed_mnem_size: {
180155+
const fixed_mnem_size: Memory.Size = switch (mnem_tag) {
180156+
.clflush => .byte,
180157+
.fldcw, .fnstcw, .fstcw, .fnstsw, .fstsw => .word,
180158+
.fldenv, .fnstenv, .fstenv => .none,
180159+
.frstor, .fsave, .fnsave, .fxrstor, .fxrstor64, .fxsave, .fxsave64 => .none,
180160+
.in => {
180161+
mnem_size.op_has_size.unset(0);
180162+
break :fixed_mnem_size;
180163+
},
180164+
.invlpg => .none,
180165+
.invpcid => .xword,
180166+
.ldmxcsr, .stmxcsr, .vldmxcsr, .vstmxcsr => .dword,
180167+
.out => {
180168+
mnem_size.op_has_size.unset(1);
180169+
break :fixed_mnem_size;
180170+
},
180171+
else => break :fixed_mnem_size,
180172+
};
180173+
if (mnem_size.size != .none and mnem_size.size != fixed_mnem_size)
180159180174
return self.fail("invalid size: '{s}'", .{mnem_str});
180160-
mnem_size.size = fixed_mnem_size;
180175+
mnem_size = .init(fixed_mnem_size);
180161180176
}
180162180177

180163180178
var ops: [4]Operand = @splat(.none);
180164180179
var ops_len: usize = 0;
180165180180

180166180181
var last_op = false;
180167180182
var op_it = std.mem.splitScalar(u8, mnem_it.rest(), ',');
180168-
next_op: for (&ops) |*op| {
180183+
next_op: for (&ops, 0..) |*op, op_index| {
180169180184
const op_str = while (!last_op) {
180170180185
const full_str = op_it.next() orelse break :next_op;
180171180186
const code_str = if (std.mem.indexOfScalar(u8, full_str, '#') orelse
@@ -180187,13 +180202,13 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
180187180202
op.* = .{ .mem = .{
180188180203
.base = .{ .reg = reg },
180189180204
.mod = .{ .rm = .{
180190-
.size = mnem_size.use() orelse
180205+
.size = mnem_size.use(op_index) orelse
180191180206
return self.fail("unknown size: '{s}'", .{op_str}),
180192180207
.disp = disp,
180193180208
} },
180194180209
} };
180195180210
} else {
180196-
if (mnem_size.use()) |size| if (reg.size().bitSize(self.target) != size.bitSize(self.target))
180211+
if (mnem_size.use(op_index)) |size| if (reg.size().bitSize(self.target) != size.bitSize(self.target))
180197180212
return self.fail("invalid register size: '{s}'", .{op_str});
180198180213
op.* = .{ .reg = reg };
180199180214
}
@@ -180212,14 +180227,14 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
180212180227
else
180213180228
return self.fail("invalid modifier: '{s}'", .{modifier}),
180214180229
.register => |reg| if (std.mem.eql(u8, modifier, ""))
180215-
.{ .reg = if (mnem_size.use()) |size| reg.toSize(size, self.target) else reg }
180230+
.{ .reg = if (mnem_size.use(op_index)) |size| reg.toSize(size, self.target) else reg }
180216180231
else
180217180232
return self.fail("invalid modifier: '{s}'", .{modifier}),
180218180233
.memory => |addr| if (std.mem.eql(u8, modifier, "") or std.mem.eql(u8, modifier, "P"))
180219180234
.{ .mem = .{
180220180235
.base = .{ .reg = .ds },
180221180236
.mod = .{ .rm = .{
180222-
.size = mnem_size.use() orelse
180237+
.size = mnem_size.use(op_index) orelse
180223180238
return self.fail("unknown size: '{s}'", .{op_str}),
180224180239
.disp = @intCast(@as(i64, @bitCast(addr))),
180225180240
} },
@@ -180230,7 +180245,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
180230180245
.{ .mem = .{
180231180246
.base = .{ .reg = reg_off.reg },
180232180247
.mod = .{ .rm = .{
180233-
.size = mnem_size.use() orelse
180248+
.size = mnem_size.use(op_index) orelse
180234180249
return self.fail("unknown size: '{s}'", .{op_str}),
180235180250
.disp = reg_off.off,
180236180251
} },
@@ -180241,7 +180256,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
180241180256
.{ .mem = .{
180242180257
.base = .{ .frame = frame_addr.index },
180243180258
.mod = .{ .rm = .{
180244-
.size = mnem_size.use() orelse
180259+
.size = mnem_size.use(op_index) orelse
180245180260
return self.fail("unknown size: '{s}'", .{op_str}),
180246180261
.disp = frame_addr.off,
180247180262
} },
@@ -180323,7 +180338,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
180323180338
else
180324180339
.none,
180325180340
.mod = .{ .rm = .{
180326-
.size = mnem_size.use() orelse return self.fail("unknown size: '{s}'", .{op_str}),
180341+
.size = mnem_size.use(op_index) orelse return self.fail("unknown size: '{s}'", .{op_str}),
180327180342
.index = if (index_str.len > 0)
180328180343
parseRegName(index_str["%%".len..]) orelse
180329180344
return self.fail("invalid index register: '{s}'", .{op_str})
@@ -180376,14 +180391,14 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
180376180391

180377180392
// convert from att syntax to intel syntax
180378180393
std.mem.reverse(Operand, ops[0..ops_len]);
180379-
if (!mnem_size.used) if (mnem_size.size) |size| {
180394+
if (mnem_size.size != .none and !mnem_size.used) {
180380180395
comptime var max_mnem_len: usize = 0;
180381180396
inline for (@typeInfo(encoder.Instruction.Mnemonic).@"enum".fields) |mnem|
180382180397
max_mnem_len = @max(mnem.name.len, max_mnem_len);
180383180398
var intel_mnem_buf: [max_mnem_len + 1]u8 = undefined;
180384180399
const intel_mnem_str = std.fmt.bufPrint(&intel_mnem_buf, "{s}{c}", .{
180385180400
@tagName(mnem_tag),
180386-
@as(u8, switch (size) {
180401+
@as(u8, switch (mnem_size.size) {
180387180402
.byte => 'b',
180388180403
.word => 'w',
180389180404
.dword => 'd',
@@ -180393,7 +180408,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
180393180408
}),
180394180409
}) catch unreachable;
180395180410
if (std.meta.stringToEnum(encoder.Instruction.Mnemonic, intel_mnem_str)) |intel_mnem_tag| mnem_tag = intel_mnem_tag;
180396-
};
180411+
}
180397180412
const mnem_name = @tagName(mnem_tag);
180398180413
const mnem_fixed_tag: Mir.Inst.FixedTag = if (prefix == .directive)
180399180414
.{ ._, .pseudo }

0 commit comments

Comments
 (0)