| ... | @@ -180114,50 +180114,65 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -180114,50 +180114,65 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180114 | } | 180114 | } |
| 180115 | | 180115 | |
| 180116 | var mnem_size: struct { | 180116 | var mnem_size: struct { |
| | 180117 | op_has_size: std.StaticBitSet(4), |
| | 180118 | size: Memory.Size, |
| 180117 | used: bool, | 180119 | used: bool, |
| 180118 | size: ?Memory.Size, | 180120 | fn init(size: ?Memory.Size) @This() { |
| 180119 | fn use(size: *@This()) ?Memory.Size { | 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; |
| 180120 | size.used = true; | 180129 | size.used = true; |
| 180121 | return size.size; | 180130 | return size.size; |
| 180122 | } | 180131 | } |
| 180123 | } = .{ | 180132 | } = .init(if (prefix == .directive) |
| 180124 | .used = false, | 180133 | null |
| 180125 | .size = if (prefix == .directive) | 180134 | else if (std.mem.endsWith(u8, mnem_str, "b")) |
| 180126 | null | 180135 | .byte |
| 180127 | else if (std.mem.endsWith(u8, mnem_str, "b")) | 180136 | else if (std.mem.endsWith(u8, mnem_str, "w")) |
| 180128 | .byte | 180137 | .word |
| 180129 | else if (std.mem.endsWith(u8, mnem_str, "w")) | 180138 | else if (std.mem.endsWith(u8, mnem_str, "l")) |
| 180130 | .word | 180139 | .dword |
| 180131 | else if (std.mem.endsWith(u8, mnem_str, "l")) | 180140 | else if (std.mem.endsWith(u8, mnem_str, "q") and |
| 180132 | .dword | 180141 | (std.mem.indexOfScalar(u8, "vp", mnem_str[0]) == null or !std.mem.endsWith(u8, mnem_str, "dq"))) |
| 180133 | else if (std.mem.endsWith(u8, mnem_str, "q") and | 180142 | .qword |
| 180134 | (std.mem.indexOfScalar(u8, "vp", mnem_str[0]) == null or !std.mem.endsWith(u8, mnem_str, "dq"))) | 180143 | else if (std.mem.endsWith(u8, mnem_str, "t")) |
| 180135 | .qword | 180144 | .tbyte |
| 180136 | else if (std.mem.endsWith(u8, mnem_str, "t")) | 180145 | else |
| 180137 | .tbyte | 180146 | null); |
| 180138 | else | | |
| 180139 | null, | | |
| 180140 | }; | | |
| 180141 | var mnem_tag = while (true) break std.meta.stringToEnum( | 180147 | var mnem_tag = while (true) break std.meta.stringToEnum( |
| 180142 | encoder.Instruction.Mnemonic, | 180148 | encoder.Instruction.Mnemonic, |
| 180143 | mnem_str[0 .. mnem_str.len - @intFromBool(mnem_size.size != null)], | 180149 | mnem_str[0 .. mnem_str.len - @intFromBool(mnem_size.size != .none)], |
| 180144 | ) orelse if (mnem_size.size) |_| { | 180150 | ) orelse if (mnem_size.size != .none) { |
| 180145 | mnem_size.size = null; | 180151 | mnem_size = .init(null); |
| 180146 | continue; | 180152 | continue; |
| 180147 | } else return self.fail("invalid mnemonic: '{s}'", .{mnem_str}); | 180153 | } else return self.fail("invalid mnemonic: '{s}'", .{mnem_str}); |
| 180148 | if (@as(?Memory.Size, switch (mnem_tag) { | 180154 | fixed_mnem_size: { |
| 180149 | .clflush => .byte, | 180155 | const fixed_mnem_size: Memory.Size = switch (mnem_tag) { |
| 180150 | .fldcw, .fnstcw, .fstcw, .fnstsw, .fstsw => .word, | 180156 | .clflush => .byte, |
| 180151 | .fldenv, .fnstenv, .fstenv => .none, | 180157 | .fldcw, .fnstcw, .fstcw, .fnstsw, .fstsw => .word, |
| 180152 | .frstor, .fsave, .fnsave, .fxrstor, .fxrstor64, .fxsave, .fxsave64 => .none, | 180158 | .fldenv, .fnstenv, .fstenv => .none, |
| 180153 | .invlpg => .none, | 180159 | .frstor, .fsave, .fnsave, .fxrstor, .fxrstor64, .fxsave, .fxsave64 => .none, |
| 180154 | .invpcid => .xword, | 180160 | .in => { |
| 180155 | .ldmxcsr, .stmxcsr, .vldmxcsr, .vstmxcsr => .dword, | 180161 | mnem_size.op_has_size.unset(0); |
| 180156 | else => null, | 180162 | break :fixed_mnem_size; |
| 180157 | })) |fixed_mnem_size| { | 180163 | }, |
| 180158 | if (mnem_size.size) |size| if (size != fixed_mnem_size) | 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) |
| 180159 | return self.fail("invalid size: '{s}'", .{mnem_str}); | 180174 | return self.fail("invalid size: '{s}'", .{mnem_str}); |
| 180160 | mnem_size.size = fixed_mnem_size; | 180175 | mnem_size = .init(fixed_mnem_size); |
| 180161 | } | 180176 | } |
| 180162 | | 180177 | |
| 180163 | var ops: [4]Operand = @splat(.none); | 180178 | var ops: [4]Operand = @splat(.none); |
| ... | @@ -180165,7 +180180,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -180165,7 +180180,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180165 | | 180180 | |
| 180166 | var last_op = false; | 180181 | var last_op = false; |
| 180167 | var op_it = std.mem.splitScalar(u8, mnem_it.rest(), ','); | 180182 | 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| { |
| 180169 | const op_str = while (!last_op) { | 180184 | const op_str = while (!last_op) { |
| 180170 | const full_str = op_it.next() orelse break :next_op; | 180185 | const full_str = op_it.next() orelse break :next_op; |
| 180171 | const code_str = if (std.mem.indexOfScalar(u8, full_str, '#') orelse | 180186 | const code_str = if (std.mem.indexOfScalar(u8, full_str, '#') orelse |
| ... | @@ -180187,13 +180202,13 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -180187,13 +180202,13 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180187 | op.* = .{ .mem = .{ | 180202 | op.* = .{ .mem = .{ |
| 180188 | .base = .{ .reg = reg }, | 180203 | .base = .{ .reg = reg }, |
| 180189 | .mod = .{ .rm = .{ | 180204 | .mod = .{ .rm = .{ |
| 180190 | .size = mnem_size.use() orelse | 180205 | .size = mnem_size.use(op_index) orelse |
| 180191 | return self.fail("unknown size: '{s}'", .{op_str}), | 180206 | return self.fail("unknown size: '{s}'", .{op_str}), |
| 180192 | .disp = disp, | 180207 | .disp = disp, |
| 180193 | } }, | 180208 | } }, |
| 180194 | } }; | 180209 | } }; |
| 180195 | } else { | 180210 | } 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)) |
| 180197 | return self.fail("invalid register size: '{s}'", .{op_str}); | 180212 | return self.fail("invalid register size: '{s}'", .{op_str}); |
| 180198 | op.* = .{ .reg = reg }; | 180213 | op.* = .{ .reg = reg }; |
| 180199 | } | 180214 | } |
| ... | @@ -180212,14 +180227,14 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -180212,14 +180227,14 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180212 | else | 180227 | else |
| 180213 | return self.fail("invalid modifier: '{s}'", .{modifier}), | 180228 | return self.fail("invalid modifier: '{s}'", .{modifier}), |
| 180214 | .register => |reg| if (std.mem.eql(u8, modifier, "")) | 180229 | .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 } |
| 180216 | else | 180231 | else |
| 180217 | return self.fail("invalid modifier: '{s}'", .{modifier}), | 180232 | return self.fail("invalid modifier: '{s}'", .{modifier}), |
| 180218 | .memory => |addr| if (std.mem.eql(u8, modifier, "") or std.mem.eql(u8, modifier, "P")) | 180233 | .memory => |addr| if (std.mem.eql(u8, modifier, "") or std.mem.eql(u8, modifier, "P")) |
| 180219 | .{ .mem = .{ | 180234 | .{ .mem = .{ |
| 180220 | .base = .{ .reg = .ds }, | 180235 | .base = .{ .reg = .ds }, |
| 180221 | .mod = .{ .rm = .{ | 180236 | .mod = .{ .rm = .{ |
| 180222 | .size = mnem_size.use() orelse | 180237 | .size = mnem_size.use(op_index) orelse |
| 180223 | return self.fail("unknown size: '{s}'", .{op_str}), | 180238 | return self.fail("unknown size: '{s}'", .{op_str}), |
| 180224 | .disp = @intCast(@as(i64, @bitCast(addr))), | 180239 | .disp = @intCast(@as(i64, @bitCast(addr))), |
| 180225 | } }, | 180240 | } }, |
| ... | @@ -180230,7 +180245,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -180230,7 +180245,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180230 | .{ .mem = .{ | 180245 | .{ .mem = .{ |
| 180231 | .base = .{ .reg = reg_off.reg }, | 180246 | .base = .{ .reg = reg_off.reg }, |
| 180232 | .mod = .{ .rm = .{ | 180247 | .mod = .{ .rm = .{ |
| 180233 | .size = mnem_size.use() orelse | 180248 | .size = mnem_size.use(op_index) orelse |
| 180234 | return self.fail("unknown size: '{s}'", .{op_str}), | 180249 | return self.fail("unknown size: '{s}'", .{op_str}), |
| 180235 | .disp = reg_off.off, | 180250 | .disp = reg_off.off, |
| 180236 | } }, | 180251 | } }, |
| ... | @@ -180241,7 +180256,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -180241,7 +180256,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180241 | .{ .mem = .{ | 180256 | .{ .mem = .{ |
| 180242 | .base = .{ .frame = frame_addr.index }, | 180257 | .base = .{ .frame = frame_addr.index }, |
| 180243 | .mod = .{ .rm = .{ | 180258 | .mod = .{ .rm = .{ |
| 180244 | .size = mnem_size.use() orelse | 180259 | .size = mnem_size.use(op_index) orelse |
| 180245 | return self.fail("unknown size: '{s}'", .{op_str}), | 180260 | return self.fail("unknown size: '{s}'", .{op_str}), |
| 180246 | .disp = frame_addr.off, | 180261 | .disp = frame_addr.off, |
| 180247 | } }, | 180262 | } }, |
| ... | @@ -180323,7 +180338,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -180323,7 +180338,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180323 | else | 180338 | else |
| 180324 | .none, | 180339 | .none, |
| 180325 | .mod = .{ .rm = .{ | 180340 | .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}), |
| 180327 | .index = if (index_str.len > 0) | 180342 | .index = if (index_str.len > 0) |
| 180328 | parseRegName(index_str["%%".len..]) orelse | 180343 | parseRegName(index_str["%%".len..]) orelse |
| 180329 | return self.fail("invalid index register: '{s}'", .{op_str}) | 180344 | return self.fail("invalid index register: '{s}'", .{op_str}) |
| ... | @@ -180376,14 +180391,14 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -180376,14 +180391,14 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180376 | | 180391 | |
| 180377 | // convert from att syntax to intel syntax | 180392 | // convert from att syntax to intel syntax |
| 180378 | std.mem.reverse(Operand, ops[0..ops_len]); | 180393 | 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) { |
| 180380 | comptime var max_mnem_len: usize = 0; | 180395 | comptime var max_mnem_len: usize = 0; |
| 180381 | inline for (@typeInfo(encoder.Instruction.Mnemonic).@"enum".fields) |mnem| | 180396 | inline for (@typeInfo(encoder.Instruction.Mnemonic).@"enum".fields) |mnem| |
| 180382 | max_mnem_len = @max(mnem.name.len, max_mnem_len); | 180397 | max_mnem_len = @max(mnem.name.len, max_mnem_len); |
| 180383 | var intel_mnem_buf: [max_mnem_len + 1]u8 = undefined; | 180398 | var intel_mnem_buf: [max_mnem_len + 1]u8 = undefined; |
| 180384 | const intel_mnem_str = std.fmt.bufPrint(&intel_mnem_buf, "{s}{c}", .{ | 180399 | const intel_mnem_str = std.fmt.bufPrint(&intel_mnem_buf, "{s}{c}", .{ |
| 180385 | @tagName(mnem_tag), | 180400 | @tagName(mnem_tag), |
| 180386 | @as(u8, switch (size) { | 180401 | @as(u8, switch (mnem_size.size) { |
| 180387 | .byte => 'b', | 180402 | .byte => 'b', |
| 180388 | .word => 'w', | 180403 | .word => 'w', |
| 180389 | .dword => 'd', | 180404 | .dword => 'd', |
| ... | @@ -180393,7 +180408,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -180393,7 +180408,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180393 | }), | 180408 | }), |
| 180394 | }) catch unreachable; | 180409 | }) catch unreachable; |
| 180395 | if (std.meta.stringToEnum(encoder.Instruction.Mnemonic, intel_mnem_str)) |intel_mnem_tag| mnem_tag = intel_mnem_tag; | 180410 | if (std.meta.stringToEnum(encoder.Instruction.Mnemonic, intel_mnem_str)) |intel_mnem_tag| mnem_tag = intel_mnem_tag; |
| 180396 | }; | 180411 | } |
| 180397 | const mnem_name = @tagName(mnem_tag); | 180412 | const mnem_name = @tagName(mnem_tag); |
| 180398 | const mnem_fixed_tag: Mir.Inst.FixedTag = if (prefix == .directive) | 180413 | const mnem_fixed_tag: Mir.Inst.FixedTag = if (prefix == .directive) |
| 180399 | .{ ._, .pseudo } | 180414 | .{ ._, .pseudo } |