| ... | @@ -54,7 +54,34 @@ pub const Instruction = struct { | ... | @@ -54,7 +54,34 @@ pub const Instruction = struct { |
| 54 | }; | 54 | }; |
| 55 | } | 55 | } |
| 56 | | 56 | |
| 57 | pub fn fmtPrint(op: Operand, enc_op: Encoding.Op, writer: anytype) @TypeOf(writer).Error!void { | 57 | fn format( |
| | 58 | op: Operand, |
| | 59 | comptime unused_format_string: []const u8, |
| | 60 | options: std.fmt.FormatOptions, |
| | 61 | writer: anytype, |
| | 62 | ) !void { |
| | 63 | _ = op; |
| | 64 | _ = unused_format_string; |
| | 65 | _ = options; |
| | 66 | _ = writer; |
| | 67 | @compileError("do not format Operand directly; use fmtPrint() instead"); |
| | 68 | } |
| | 69 | |
| | 70 | const FormatContext = struct { |
| | 71 | op: Operand, |
| | 72 | enc_op: Encoding.Op, |
| | 73 | }; |
| | 74 | |
| | 75 | fn fmt( |
| | 76 | ctx: FormatContext, |
| | 77 | comptime unused_format_string: []const u8, |
| | 78 | options: std.fmt.FormatOptions, |
| | 79 | writer: anytype, |
| | 80 | ) @TypeOf(writer).Error!void { |
| | 81 | _ = unused_format_string; |
| | 82 | _ = options; |
| | 83 | const op = ctx.op; |
| | 84 | const enc_op = ctx.enc_op; |
| 58 | switch (op) { | 85 | switch (op) { |
| 59 | .none => {}, | 86 | .none => {}, |
| 60 | .reg => |reg| try writer.writeAll(@tagName(reg)), | 87 | .reg => |reg| try writer.writeAll(@tagName(reg)), |
| ... | @@ -105,6 +132,13 @@ pub const Instruction = struct { | ... | @@ -105,6 +132,13 @@ pub const Instruction = struct { |
| 105 | .imm => |imm| try writer.print("0x{x}", .{imm.asUnsigned(enc_op.bitSize())}), | 132 | .imm => |imm| try writer.print("0x{x}", .{imm.asUnsigned(enc_op.bitSize())}), |
| 106 | } | 133 | } |
| 107 | } | 134 | } |
| | 135 | |
| | 136 | pub fn fmtPrint(op: Operand, enc_op: Encoding.Op) std.fmt.Formatter(fmt) { |
| | 137 | return .{ .data = .{ |
| | 138 | .op = op, |
| | 139 | .enc_op = enc_op, |
| | 140 | } }; |
| | 141 | } |
| 108 | }; | 142 | }; |
| 109 | | 143 | |
| 110 | pub fn new(prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) !Instruction { | 144 | pub fn new(prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) !Instruction { |
| ... | @@ -130,14 +164,21 @@ pub const Instruction = struct { | ... | @@ -130,14 +164,21 @@ pub const Instruction = struct { |
| 130 | return inst; | 164 | return inst; |
| 131 | } | 165 | } |
| 132 | | 166 | |
| 133 | pub fn fmtPrint(inst: Instruction, writer: anytype) @TypeOf(writer).Error!void { | 167 | pub fn format( |
| | 168 | inst: Instruction, |
| | 169 | comptime unused_format_string: []const u8, |
| | 170 | options: std.fmt.FormatOptions, |
| | 171 | writer: anytype, |
| | 172 | ) @TypeOf(writer).Error!void { |
| | 173 | _ = unused_format_string; |
| | 174 | _ = options; |
| 134 | if (inst.prefix != .none) try writer.print("{s} ", .{@tagName(inst.prefix)}); | 175 | if (inst.prefix != .none) try writer.print("{s} ", .{@tagName(inst.prefix)}); |
| 135 | try writer.print("{s}", .{@tagName(inst.encoding.mnemonic)}); | 176 | try writer.print("{s}", .{@tagName(inst.encoding.mnemonic)}); |
| 136 | for (inst.ops, inst.encoding.data.ops, 0..) |op, enc, i| { | 177 | for (inst.ops, inst.encoding.data.ops, 0..) |op, enc, i| { |
| 137 | if (op == .none) break; | 178 | if (op == .none) break; |
| 138 | if (i > 0) try writer.writeByte(','); | 179 | if (i > 0) try writer.writeByte(','); |
| 139 | try writer.writeByte(' '); | 180 | try writer.writeByte(' '); |
| 140 | try op.fmtPrint(enc, writer); | 181 | try writer.print("{}", .{op.fmtPrint(enc)}); |
| 141 | } | 182 | } |
| 142 | } | 183 | } |
| 143 | | 184 | |