| ... | ... | @@ -180114,50 +180114,65 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180114 | 180114 | } |
| 180115 | 180115 | |
| 180116 | 180116 | var mnem_size: struct { |
| 180117 | op_has_size: std.StaticBitSet(4), |
| 180118 | size: Memory.Size, |
| 180117 | 180119 | 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; |
| 180120 | 180129 | size.used = true; |
| 180121 | 180130 | return size.size; |
| 180122 | 180131 | } |
| 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); |
| 180141 | 180147 | var mnem_tag = while (true) break std.meta.stringToEnum( |
| 180142 | 180148 | 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); |
| 180146 | 180152 | continue; |
| 180147 | 180153 | } 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) |
| 180159 | 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 | 180178 | var ops: [4]Operand = @splat(.none); |
| ... | ... | @@ -180165,7 +180180,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180165 | 180180 | |
| 180166 | 180181 | var last_op = false; |
| 180167 | 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 | 180184 | const op_str = while (!last_op) { |
| 180170 | 180185 | const full_str = op_it.next() orelse break :next_op; |
| 180171 | 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 | 180202 | op.* = .{ .mem = .{ |
| 180188 | 180203 | .base = .{ .reg = reg }, |
| 180189 | 180204 | .mod = .{ .rm = .{ |
| 180190 | | .size = mnem_size.use() orelse |
| 180205 | .size = mnem_size.use(op_index) orelse |
| 180191 | 180206 | return self.fail("unknown size: '{s}'", .{op_str}), |
| 180192 | 180207 | .disp = disp, |
| 180193 | 180208 | } }, |
| 180194 | 180209 | } }; |
| 180195 | 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 | 180212 | return self.fail("invalid register size: '{s}'", .{op_str}); |
| 180198 | 180213 | op.* = .{ .reg = reg }; |
| 180199 | 180214 | } |
| ... | ... | @@ -180212,14 +180227,14 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180212 | 180227 | else |
| 180213 | 180228 | return self.fail("invalid modifier: '{s}'", .{modifier}), |
| 180214 | 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 | 180231 | else |
| 180217 | 180232 | return self.fail("invalid modifier: '{s}'", .{modifier}), |
| 180218 | 180233 | .memory => |addr| if (std.mem.eql(u8, modifier, "") or std.mem.eql(u8, modifier, "P")) |
| 180219 | 180234 | .{ .mem = .{ |
| 180220 | 180235 | .base = .{ .reg = .ds }, |
| 180221 | 180236 | .mod = .{ .rm = .{ |
| 180222 | | .size = mnem_size.use() orelse |
| 180237 | .size = mnem_size.use(op_index) orelse |
| 180223 | 180238 | return self.fail("unknown size: '{s}'", .{op_str}), |
| 180224 | 180239 | .disp = @intCast(@as(i64, @bitCast(addr))), |
| 180225 | 180240 | } }, |
| ... | ... | @@ -180230,7 +180245,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180230 | 180245 | .{ .mem = .{ |
| 180231 | 180246 | .base = .{ .reg = reg_off.reg }, |
| 180232 | 180247 | .mod = .{ .rm = .{ |
| 180233 | | .size = mnem_size.use() orelse |
| 180248 | .size = mnem_size.use(op_index) orelse |
| 180234 | 180249 | return self.fail("unknown size: '{s}'", .{op_str}), |
| 180235 | 180250 | .disp = reg_off.off, |
| 180236 | 180251 | } }, |
| ... | ... | @@ -180241,7 +180256,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180241 | 180256 | .{ .mem = .{ |
| 180242 | 180257 | .base = .{ .frame = frame_addr.index }, |
| 180243 | 180258 | .mod = .{ .rm = .{ |
| 180244 | | .size = mnem_size.use() orelse |
| 180259 | .size = mnem_size.use(op_index) orelse |
| 180245 | 180260 | return self.fail("unknown size: '{s}'", .{op_str}), |
| 180246 | 180261 | .disp = frame_addr.off, |
| 180247 | 180262 | } }, |
| ... | ... | @@ -180323,7 +180338,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180323 | 180338 | else |
| 180324 | 180339 | .none, |
| 180325 | 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 | 180342 | .index = if (index_str.len > 0) |
| 180328 | 180343 | parseRegName(index_str["%%".len..]) orelse |
| 180329 | 180344 | return self.fail("invalid index register: '{s}'", .{op_str}) |
| ... | ... | @@ -180376,14 +180391,14 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180376 | 180391 | |
| 180377 | 180392 | // convert from att syntax to intel syntax |
| 180378 | 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 | 180395 | comptime var max_mnem_len: usize = 0; |
| 180381 | 180396 | inline for (@typeInfo(encoder.Instruction.Mnemonic).@"enum".fields) |mnem| |
| 180382 | 180397 | max_mnem_len = @max(mnem.name.len, max_mnem_len); |
| 180383 | 180398 | var intel_mnem_buf: [max_mnem_len + 1]u8 = undefined; |
| 180384 | 180399 | const intel_mnem_str = std.fmt.bufPrint(&intel_mnem_buf, "{s}{c}", .{ |
| 180385 | 180400 | @tagName(mnem_tag), |
| 180386 | | @as(u8, switch (size) { |
| 180401 | @as(u8, switch (mnem_size.size) { |
| 180387 | 180402 | .byte => 'b', |
| 180388 | 180403 | .word => 'w', |
| 180389 | 180404 | .dword => 'd', |
| ... | ... | @@ -180393,7 +180408,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180393 | 180408 | }), |
| 180394 | 180409 | }) catch unreachable; |
| 180395 | 180410 | if (std.meta.stringToEnum(encoder.Instruction.Mnemonic, intel_mnem_str)) |intel_mnem_tag| mnem_tag = intel_mnem_tag; |
| 180396 | | }; |
| 180411 | } |
| 180397 | 180412 | const mnem_name = @tagName(mnem_tag); |
| 180398 | 180413 | const mnem_fixed_tag: Mir.Inst.FixedTag = if (prefix == .directive) |
| 180399 | 180414 | .{ ._, .pseudo } |