| ... | @@ -177397,7 +177397,10 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -177397,7 +177397,10 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 177397 | label_gop.value_ptr.target = @intCast(self.mir_instructions.len); | 177397 | label_gop.value_ptr.target = @intCast(self.mir_instructions.len); |
| 177398 | } else continue; | 177398 | } else continue; |
| 177399 | if (mnem_str[0] == '.') { | 177399 | if (mnem_str[0] == '.') { |
| 177400 | if (prefix != .none) return self.fail("prefixed directive: '{s} {s}'", .{ @tagName(prefix), mnem_str }); | 177400 | if (prefix != .none) return self.fail("prefixed directive: '{s} {s}'", .{ |
| | 177401 | @tagName(prefix), |
| | 177402 | mnem_str, |
| | 177403 | }); |
| 177401 | prefix = .directive; | 177404 | prefix = .directive; |
| 177402 | } | 177405 | } |
| 177403 | | 177406 | |
| ... | @@ -177426,7 +177429,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -177426,7 +177429,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 177426 | else if (std.mem.endsWith(u8, mnem_str, "l")) | 177429 | else if (std.mem.endsWith(u8, mnem_str, "l")) |
| 177427 | .dword | 177430 | .dword |
| 177428 | else if (std.mem.endsWith(u8, mnem_str, "q") and | 177431 | else if (std.mem.endsWith(u8, mnem_str, "q") and |
| 177429 | (std.mem.indexOfScalar(u8, "vp", mnem_str[0]) == null or !std.mem.endsWith(u8, mnem_str, "dq"))) | 177432 | (std.mem.indexOfScalar(u8, "vp", mnem_str[0]) == null or |
| | 177433 | !std.mem.endsWith(u8, mnem_str, "dq"))) |
| 177430 | .qword | 177434 | .qword |
| 177431 | else if (std.mem.endsWith(u8, mnem_str, "t")) | 177435 | else if (std.mem.endsWith(u8, mnem_str, "t")) |
| 177432 | .tbyte | 177436 | .tbyte |
| ... | @@ -177463,23 +177467,40 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -177463,23 +177467,40 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 177463 | mnem_size = .init(fixed_mnem_size); | 177467 | mnem_size = .init(fixed_mnem_size); |
| 177464 | } | 177468 | } |
| 177465 | | 177469 | |
| | 177470 | const ops_str = mnem_it.rest(); |
| | 177471 | var ops_index: usize = 0; |
| 177466 | var ops: [4]Operand = @splat(.none); | 177472 | var ops: [4]Operand = @splat(.none); |
| 177467 | var ops_len: usize = 0; | 177473 | var ops_len: usize = 0; |
| 177468 | | | |
| 177469 | var last_op = false; | | |
| 177470 | var op_it = std.mem.splitScalar(u8, mnem_it.rest(), ','); | | |
| 177471 | next_op: for (&ops, 0..) |*op, op_index| { | 177474 | next_op: for (&ops, 0..) |*op, op_index| { |
| 177472 | const op_str = while (!last_op) { | 177475 | const op_str = while (true) { |
| 177473 | const full_str = op_it.next() orelse break :next_op; | 177476 | const op_start = ops_index; |
| 177474 | const code_str = if (std.mem.indexOfScalar(u8, full_str, '#') orelse | 177477 | if (ops_str.len - op_start == 0) break :next_op; |
| 177475 | std.mem.indexOf(u8, full_str, "//")) |comment| | 177478 | const full_op_str = while (true) { |
| 177476 | code: { | 177479 | const op_end = std.mem.findAnyPos(u8, ops_str, ops_index, ",(") orelse { |
| 177477 | last_op = true; | 177480 | ops_index = ops_str.len; |
| 177478 | break :code full_str[0..comment]; | 177481 | break ops_str[op_start..]; |
| 177479 | } else full_str; | 177482 | }; |
| 177480 | const trim_str = std.mem.trim(u8, code_str, " \t*"); | 177483 | switch (ops_str[op_end]) { |
| 177481 | if (trim_str.len > 0) break trim_str; | 177484 | else => unreachable, |
| 177482 | } else break; | 177485 | ',' => { |
| | 177486 | ops_index = op_end + 1; |
| | 177487 | break ops_str[op_start..op_end]; |
| | 177488 | }, |
| | 177489 | '(' => ops_index = (std.mem.findScalarPos(u8, ops_str, op_end + 1, ')') orelse { |
| | 177490 | ops_index = ops_str.len; |
| | 177491 | break ops_str[op_start..]; |
| | 177492 | }) + 1, |
| | 177493 | } |
| | 177494 | }; |
| | 177495 | const untrimmed_op_str = if (std.mem.indexOfScalar(u8, full_op_str, '#') orelse |
| | 177496 | std.mem.indexOf(u8, full_op_str, "//")) |comment| |
| | 177497 | untrimmed_op_str: { |
| | 177498 | ops_index = ops_str.len; |
| | 177499 | break :untrimmed_op_str full_op_str[0..comment]; |
| | 177500 | } else full_op_str; |
| | 177501 | const trimmed_op_str = std.mem.trim(u8, untrimmed_op_str, " \t*"); |
| | 177502 | if (trimmed_op_str.len > 0) break trimmed_op_str; |
| | 177503 | }; |
| 177483 | if (std.mem.startsWith(u8, op_str, "%%")) { | 177504 | if (std.mem.startsWith(u8, op_str, "%%")) { |
| 177484 | const colon = std.mem.indexOfScalarPos(u8, op_str, "%%".len + 2, ':'); | 177505 | const colon = std.mem.indexOfScalarPos(u8, op_str, "%%".len + 2, ':'); |
| 177485 | const reg = parseRegName(op_str["%%".len .. colon orelse op_str.len]) orelse | 177506 | const reg = parseRegName(op_str["%%".len .. colon orelse op_str.len]) orelse |
| ... | @@ -177496,7 +177517,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -177496,7 +177517,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 177496 | } }, | 177517 | } }, |
| 177497 | } }; | 177518 | } }; |
| 177498 | } else { | 177519 | } else { |
| 177499 | if (mnem_size.use(op_index)) |size| if (reg.size().bitSize(self.target) != size.bitSize(self.target)) | 177520 | if (mnem_size.use(op_index)) |size| if (reg.size().bitSize(self.target) != |
| | 177521 | size.bitSize(self.target)) |
| 177500 | return self.fail("invalid register size: '{s}'", .{op_str}); | 177522 | return self.fail("invalid register size: '{s}'", .{op_str}); |
| 177501 | op.* = .{ .reg = reg }; | 177523 | op.* = .{ .reg = reg }; |
| 177502 | } | 177524 | } |
| ... | @@ -177510,15 +177532,20 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -177510,15 +177532,20 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 177510 | arg_map.get(op_str["%[".len .. colon orelse op_str.len - "]".len]) orelse | 177532 | arg_map.get(op_str["%[".len .. colon orelse op_str.len - "]".len]) orelse |
| 177511 | return self.fail("no matching constraint: '{s}'", .{op_str}) | 177533 | return self.fail("no matching constraint: '{s}'", .{op_str}) |
| 177512 | ]) { | 177534 | ]) { |
| 177513 | .immediate => |imm| if (std.mem.eql(u8, modifier, "") or std.mem.eql(u8, modifier, "c")) | 177535 | .immediate => |imm| if (std.mem.eql(u8, modifier, "") or |
| | 177536 | std.mem.eql(u8, modifier, "c")) |
| 177514 | .{ .imm = .u(imm) } | 177537 | .{ .imm = .u(imm) } |
| 177515 | else | 177538 | else |
| 177516 | return self.fail("invalid modifier: '{s}'", .{modifier}), | 177539 | return self.fail("invalid modifier: '{s}'", .{modifier}), |
| 177517 | .register => |reg| if (std.mem.eql(u8, modifier, "")) | 177540 | .register => |reg| if (std.mem.eql(u8, modifier, "")) |
| 177518 | .{ .reg = if (mnem_size.use(op_index)) |size| reg.toSize(size, self.target) else reg } | 177541 | .{ .reg = if (mnem_size.use(op_index)) |size| |
| | 177542 | reg.toSize(size, self.target) |
| | 177543 | else |
| | 177544 | reg } |
| 177519 | else | 177545 | else |
| 177520 | return self.fail("invalid modifier: '{s}'", .{modifier}), | 177546 | return self.fail("invalid modifier: '{s}'", .{modifier}), |
| 177521 | .memory => |addr| if (std.mem.eql(u8, modifier, "") or std.mem.eql(u8, modifier, "P")) | 177547 | .memory => |addr| if (std.mem.eql(u8, modifier, "") or |
| | 177548 | std.mem.eql(u8, modifier, "P")) |
| 177522 | .{ .mem = .{ | 177549 | .{ .mem = .{ |
| 177523 | .base = .{ .reg = .ds }, | 177550 | .base = .{ .reg = .ds }, |
| 177524 | .mod = .{ .rm = .{ | 177551 | .mod = .{ .rm = .{ |
| ... | @@ -177564,7 +177591,9 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -177564,7 +177591,9 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 177564 | else | 177591 | else |
| 177565 | return self.fail("invalid modifier: '{s}'", .{modifier}), | 177592 | return self.fail("invalid modifier: '{s}'", .{modifier}), |
| 177566 | .lea_extern_func => |extern_func| if (std.mem.eql(u8, modifier, "P")) | 177593 | .lea_extern_func => |extern_func| if (std.mem.eql(u8, modifier, "P")) |
| 177567 | .{ .reg = try self.copyToTmpRegister(.usize, .{ .lea_extern_func = extern_func }) } | 177594 | .{ .reg = try self.copyToTmpRegister(.usize, .{ |
| | 177595 | .lea_extern_func = extern_func, |
| | 177596 | }) } |
| 177568 | else | 177597 | else |
| 177569 | return self.fail("invalid modifier: '{s}'", .{modifier}), | 177598 | return self.fail("invalid modifier: '{s}'", .{modifier}), |
| 177570 | else => return self.fail("invalid constraint: '{s}'", .{op_str}), | 177599 | else => return self.fail("invalid constraint: '{s}'", .{op_str}), |
| ... | @@ -177579,7 +177608,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -177579,7 +177608,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 177579 | } else if (std.mem.endsWith(u8, op_str, ")")) { | 177608 | } else if (std.mem.endsWith(u8, op_str, ")")) { |
| 177580 | const open = std.mem.indexOfScalar(u8, op_str, '(') orelse | 177609 | const open = std.mem.indexOfScalar(u8, op_str, '(') orelse |
| 177581 | return self.fail("invalid operand: '{s}'", .{op_str}); | 177610 | return self.fail("invalid operand: '{s}'", .{op_str}); |
| 177582 | var sib_it = std.mem.splitScalar(u8, op_str[open + "(".len .. op_str.len - ")".len], ','); | 177611 | var sib_it = |
| | 177612 | std.mem.splitScalar(u8, op_str[open + "(".len .. op_str.len - ")".len], ','); |
| 177583 | const base_str = sib_it.next() orelse | 177613 | const base_str = sib_it.next() orelse |
| 177584 | return self.fail("invalid memory operand: '{s}'", .{op_str}); | 177614 | return self.fail("invalid memory operand: '{s}'", .{op_str}); |
| 177585 | if (base_str.len > 0 and !std.mem.startsWith(u8, base_str, "%%")) | 177615 | if (base_str.len > 0 and !std.mem.startsWith(u8, base_str, "%%")) |
| ... | @@ -177626,7 +177656,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -177626,7 +177656,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 177626 | else | 177656 | else |
| 177627 | .none, | 177657 | .none, |
| 177628 | .mod = .{ .rm = .{ | 177658 | .mod = .{ .rm = .{ |
| 177629 | .size = mnem_size.use(op_index) orelse return self.fail("unknown size: '{s}'", .{op_str}), | 177659 | .size = mnem_size.use(op_index) orelse |
| | 177660 | return self.fail("unknown size: '{s}'", .{op_str}), |
| 177630 | .index = if (index_str.len > 0) | 177661 | .index = if (index_str.len > 0) |
| 177631 | parseRegName(index_str["%%".len..]) orelse | 177662 | parseRegName(index_str["%%".len..]) orelse |
| 177632 | return self.fail("invalid index register: '{s}'", .{op_str}) | 177663 | return self.fail("invalid index register: '{s}'", .{op_str}) |
| ... | @@ -177675,7 +177706,9 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -177675,7 +177706,9 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 177675 | op.* = .{ .inst = label_gop.value_ptr.target }; | 177706 | op.* = .{ .inst = label_gop.value_ptr.target }; |
| 177676 | } else return self.fail("invalid operand: '{s}'", .{op_str}); | 177707 | } else return self.fail("invalid operand: '{s}'", .{op_str}); |
| 177677 | ops_len += 1; | 177708 | ops_len += 1; |
| 177678 | } else if (op_it.next()) |op_str| return self.fail("extra operand: '{s}'", .{op_str}); | 177709 | } else if (ops_str.len - ops_index > 0) return self.fail("extra operand: '{s}'", .{ |
| | 177710 | ops_str[ops_index..], |
| | 177711 | }); |
| 177679 | | 177712 | |
| 177680 | // convert from att syntax to intel syntax | 177713 | // convert from att syntax to intel syntax |
| 177681 | std.mem.reverse(Operand, ops[0..ops_len]); | 177714 | std.mem.reverse(Operand, ops[0..ops_len]); |
| ... | @@ -177695,7 +177728,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -177695,7 +177728,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 177695 | else => unreachable, | 177728 | else => unreachable, |
| 177696 | }), | 177729 | }), |
| 177697 | }) catch unreachable; | 177730 | }) catch unreachable; |
| 177698 | if (std.meta.stringToEnum(encoder.Instruction.Mnemonic, intel_mnem_str)) |intel_mnem_tag| mnem_tag = intel_mnem_tag; | 177731 | if (std.meta.stringToEnum(encoder.Instruction.Mnemonic, intel_mnem_str)) |intel_mnem_tag| |
| | 177732 | mnem_tag = intel_mnem_tag; |
| 177699 | } | 177733 | } |
| 177700 | const mnem_name = @tagName(mnem_tag); | 177734 | const mnem_name = @tagName(mnem_tag); |
| 177701 | const mnem_fixed_tag: Mir.Inst.FixedTag = if (prefix == .directive) | 177735 | const mnem_fixed_tag: Mir.Inst.FixedTag = if (prefix == .directive) |