lib/isa/src/x86/instruction.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const std = @import("std");
  2 const x86 = @import("root.zig");
  3 
  4 pub const Family = enum(u5) {
  5     move = 0,
  6     extend = 1,
  7     address = 2,
  8     string = 3,
  9     arithmetic = 4,
 10     logic = 5,
 11     unary = 6,
 12     shift = 7,
 13     multiply = 8,
 14     divide = 9,
 15     condition = 10,
 16     control = 11,
 17     stack = 12,
 18     swap = 13,
 19     carry = 14,
 20     nop = 15,
 21     boundary = 16,
 22     system = 17,
 23     vector = 18,
 24     exchange = 19,
 25     interrupt = 20,
 26 };
 27 
 28 pub const Operation = enum(u8) {
 29     add = 0,
 30     and_ = 1,
 31     bswap = 2,
 32     call = 3,
 33     cmc = 4,
 34     cmovae = 5,
 35     cmove = 6,
 36     cmovne = 7,
 37     cmp = 8,
 38     dec = 9,
 39     div = 10,
 40     hlt = 11,
 41     imul = 12,
 42     inc = 13,
 43     ja = 14,
 44     jae = 15,
 45     jb = 16,
 46     jbe = 17,
 47     je = 18,
 48     jmp = 19,
 49     jne = 20,
 50     lea = 21,
 51     mov = 22,
 52     movs = 23,
 53     movsx = 24,
 54     movzx = 25,
 55     mul = 26,
 56     nop = 27,
 57     not_ = 28,
 58     or_ = 29,
 59     out = 30,
 60     pop = 31,
 61     push = 32,
 62     ret = 33,
 63     rol = 34,
 64     sbb = 35,
 65     seta = 36,
 66     setae = 37,
 67     setb = 38,
 68     setbe = 39,
 69     sete = 40,
 70     setne = 41,
 71     shl = 42,
 72     shr = 43,
 73     stos = 44,
 74     sub = 45,
 75     test_ = 46,
 76     ud2 = 47,
 77     xor_ = 48,
 78     adc = 49,
 79     cli = 50,
 80     cmova = 51,
 81     cmovb = 52,
 82     cmpxchg = 53,
 83     cpuid = 54,
 84     idiv = 55,
 85     int_ = 56,
 86     movdqu = 57,
 87     movups = 58,
 88     neg = 59,
 89     pshufd = 60,
 90     pushf = 61,
 91     rdmsr = 62,
 92     ror = 63,
 93     sar = 64,
 94     sti = 65,
 95     wrmsr = 66,
 96     xchg = 67,
 97     seto = 68,
 98     jl = 69,
 99     jge = 70,
100     jle = 71,
101     jg = 72,
102     setl = 73,
103     setge = 74,
104     setle = 75,
105     setg = 76,
106 
107     pub fn family(self: Operation) Family {
108         return switch (self) {
109             .mov => .move,
110             .movsx, .movzx => .extend,
111             .lea => .address,
112             .movs, .stos => .string,
113             .add, .adc, .cmp, .sbb, .sub => .arithmetic,
114             .and_, .or_, .test_, .xor_ => .logic,
115             .dec, .inc, .neg, .not_ => .unary,
116             .rol, .ror, .sar, .shl, .shr => .shift,
117             .imul, .mul => .multiply,
118             .div, .idiv => .divide,
119             .cmova,
120             .cmovae,
121             .cmovb,
122             .cmove,
123             .cmovne,
124             .ja,
125             .jae,
126             .jb,
127             .jbe,
128             .je,
129             .jne,
130             .seta,
131             .setae,
132             .setb,
133             .setbe,
134             .sete,
135             .setne,
136             .seto,
137             .jl,
138             .jge,
139             .jle,
140             .jg,
141             .setl,
142             .setge,
143             .setle,
144             .setg,
145             => .condition,
146             .call, .jmp, .ret => .control,
147             .pop, .push, .pushf => .stack,
148             .bswap => .swap,
149             .cmc => .carry,
150             .nop => .nop,
151             .hlt, .out, .ud2 => .boundary,
152             .cli, .cpuid, .rdmsr, .sti, .wrmsr => .system,
153             .movdqu, .movups, .pshufd => .vector,
154             .cmpxchg, .xchg => .exchange,
155             .int_ => .interrupt,
156         };
157     }
158 };
159 
160 pub const implicit_registers_max: usize = 4;
161 
162 pub const Instruction = struct {
163     form: x86.Form,
164     operation: Operation,
165     family: Family,
166     bytes: u4,
167     register: ?x86.Register = null,
168     register_access: x86.Access = .none,
169     operand: x86.Operand = .none,
170     operand_access: x86.Access = .none,
171     embedded: ?x86.Register = null,
172     embedded_access: x86.Access = .none,
173     immediate: ?x86.Immediate = null,
174     relative: ?i32 = null,
175     modrm_mode: ?u2 = null,
176     modrm_operand: ?u4 = null,
177     implicit: [implicit_registers_max]x86.RegisterAccess = @splat(.{}),
178     implicit_count: u3 = 0,
179 
180     pub fn implicitRegisters(self: *const Instruction) []const x86.RegisterAccess {
181         std.debug.assert(self.implicit_count <= self.implicit.len);
182         return self.implicit[0..self.implicit_count];
183     }
184 };
185 
186 comptime {
187     std.debug.assert(@backingInt(Operation.xor_) == 48);
188     std.debug.assert(implicit_registers_max <= std.math.maxInt(u3));
189 }