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