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