lib/isa/src/x86/operand.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const std = @import("std");
  2 const x86 = @import("root.zig");
  3 
  4 pub const RegisterBank = enum(u1) {
  5     gpr = 0,
  6     vector = 1,
  7 };
  8 
  9 pub const RegisterLane = enum(u3) {
 10     low8 = 0,
 11     high8 = 1,
 12     word = 2,
 13     dword = 3,
 14     qword = 4,
 15     vector128 = 5,
 16 
 17     pub fn bytes(self: RegisterLane) u8 {
 18         return switch (self) {
 19             .low8, .high8 => 1,
 20             .word => 2,
 21             .dword => 4,
 22             .qword => 8,
 23             .vector128 => 16,
 24         };
 25     }
 26 };
 27 
 28 pub const Register = struct {
 29     bank: RegisterBank = .gpr,
 30     number: u4 = 0,
 31     lane: RegisterLane = .qword,
 32 
 33     pub fn role(self: Register) x86.Role {
 34         if (self.bank == .vector or self.lane == .high8) return .ordinary;
 35         return switch (self.number) {
 36             4 => .rsp,
 37             5 => .rbp,
 38             else => .ordinary,
 39         };
 40     }
 41 };
 42 
 43 pub const RegisterAccess = struct {
 44     register: Register = .{},
 45     access: x86.Access = .none,
 46 };
 47 
 48 pub const Segment = enum(u3) {
 49     none = 0,
 50     es = 1,
 51     cs = 2,
 52     ss = 3,
 53     ds = 4,
 54     fs = 5,
 55     gs = 6,
 56 
 57     pub fn prefixByte(self: Segment) u8 {
 58         return switch (self) {
 59             .none => 0,
 60             .es => 0x26,
 61             .cs => 0x2e,
 62             .ss => 0x36,
 63             .ds => 0x3e,
 64             .fs => 0x64,
 65             .gs => 0x65,
 66         };
 67     }
 68 };
 69 
 70 pub const Scale = enum(u2) {
 71     one = 0,
 72     two = 1,
 73     four = 2,
 74     eight = 3,
 75 
 76     pub fn factor(self: Scale) u4 {
 77         return @as(u4, 1) << @backingInt(self);
 78     }
 79 };
 80 
 81 pub const Memory = struct {
 82     kind: x86.AddressKind,
 83     width: x86.Width = .none,
 84     base: ?Register = null,
 85     index: ?Register = null,
 86     scale: Scale = .one,
 87     displacement: i32 = 0,
 88     segment: Segment = .none,
 89 };
 90 
 91 pub const Operand = union(enum) {
 92     none,
 93     register: Register,
 94     memory: Memory,
 95 };
 96 
 97 pub const ImmediateExtension = enum(u1) {
 98     none = 0,
 99     sign = 1,
100 };
101 
102 pub const Immediate = struct {
103     value: u64,
104     encoded_bytes: u4,
105     extension: ImmediateExtension,
106 
107     pub fn signed(self: Immediate) i64 {
108         std.debug.assert(std.math.isPowerOfTwo(self.encoded_bytes));
109         std.debug.assert(self.encoded_bytes <= 8);
110         return switch (self.encoded_bytes) {
111             1 => @as(i8, @bitCast(@as(u8, @truncate(self.value)))),
112             2 => @as(i16, @bitCast(@as(u16, @truncate(self.value)))),
113             4 => @as(i32, @bitCast(@as(u32, @truncate(self.value)))),
114             8 => @bitCast(self.value),
115             else => unreachable,
116         };
117     }
118 };