124 lines
3.2 KiB
Zig
124 lines
3.2 KiB
Zig
const std = @import("std");
|
|
const DW = std.dwarf;
|
|
|
|
// zig fmt: off
|
|
pub const Register = enum(u8) {
|
|
// 0 through 7, 32-bit registers. id is int value
|
|
eax, ecx, edx, ebx, esp, ebp, esi, edi,
|
|
|
|
// 8-15, 16-bit registers. id is int value - 8.
|
|
ax, cx, dx, bx, sp, bp, si, di,
|
|
|
|
// 16-23, 8-bit registers. id is int value - 16.
|
|
al, cl, dl, bl, ah, ch, dh, bh,
|
|
|
|
/// Returns the bit-width of the register.
|
|
pub fn size(self: @This()) u7 {
|
|
return switch (@enumToInt(self)) {
|
|
0...7 => 32,
|
|
8...15 => 16,
|
|
16...23 => 8,
|
|
else => unreachable,
|
|
};
|
|
}
|
|
|
|
/// Returns the register's id. This is used in practically every opcode the
|
|
/// x86 has. It is embedded in some instructions, such as the `B8 +rd` move
|
|
/// instruction, and is used in the R/M byte.
|
|
pub fn id(self: @This()) u3 {
|
|
return @truncate(u3, @enumToInt(self));
|
|
}
|
|
|
|
/// Returns the index into `callee_preserved_regs`.
|
|
pub fn allocIndex(self: Register) ?u4 {
|
|
return switch (self) {
|
|
.eax, .ax, .al => 0,
|
|
.ecx, .cx, .cl => 1,
|
|
.edx, .dx, .dl => 2,
|
|
.esi, .si => 3,
|
|
.edi, .di => 4,
|
|
else => null,
|
|
};
|
|
}
|
|
|
|
/// Convert from any register to its 32 bit alias.
|
|
pub fn to32(self: Register) Register {
|
|
return @intToEnum(Register, @as(u8, self.id()));
|
|
}
|
|
|
|
/// Convert from any register to its 16 bit alias.
|
|
pub fn to16(self: Register) Register {
|
|
return @intToEnum(Register, @as(u8, self.id()) + 8);
|
|
}
|
|
|
|
/// Convert from any register to its 8 bit alias.
|
|
pub fn to8(self: Register) Register {
|
|
return @intToEnum(Register, @as(u8, self.id()) + 16);
|
|
}
|
|
|
|
|
|
pub fn dwarfLocOp(reg: Register) u8 {
|
|
return switch (reg.to32()) {
|
|
.eax => DW.OP_reg0,
|
|
.ecx => DW.OP_reg1,
|
|
.edx => DW.OP_reg2,
|
|
.ebx => DW.OP_reg3,
|
|
.esp => DW.OP_reg4,
|
|
.ebp => DW.OP_reg5,
|
|
.esi => DW.OP_reg6,
|
|
.edi => DW.OP_reg7,
|
|
else => unreachable,
|
|
};
|
|
}
|
|
};
|
|
|
|
// zig fmt: on
|
|
|
|
pub const callee_preserved_regs = [_]Register{ .eax, .ecx, .edx, .esi, .edi };
|
|
|
|
// TODO add these to Register enum and corresponding dwarfLocOp
|
|
// // Return Address register. This is stored in `0(%esp, "")` and is not a physical register.
|
|
// RA = (8, "RA"),
|
|
//
|
|
// ST0 = (11, "st0"),
|
|
// ST1 = (12, "st1"),
|
|
// ST2 = (13, "st2"),
|
|
// ST3 = (14, "st3"),
|
|
// ST4 = (15, "st4"),
|
|
// ST5 = (16, "st5"),
|
|
// ST6 = (17, "st6"),
|
|
// ST7 = (18, "st7"),
|
|
//
|
|
// XMM0 = (21, "xmm0"),
|
|
// XMM1 = (22, "xmm1"),
|
|
// XMM2 = (23, "xmm2"),
|
|
// XMM3 = (24, "xmm3"),
|
|
// XMM4 = (25, "xmm4"),
|
|
// XMM5 = (26, "xmm5"),
|
|
// XMM6 = (27, "xmm6"),
|
|
// XMM7 = (28, "xmm7"),
|
|
//
|
|
// MM0 = (29, "mm0"),
|
|
// MM1 = (30, "mm1"),
|
|
// MM2 = (31, "mm2"),
|
|
// MM3 = (32, "mm3"),
|
|
// MM4 = (33, "mm4"),
|
|
// MM5 = (34, "mm5"),
|
|
// MM6 = (35, "mm6"),
|
|
// MM7 = (36, "mm7"),
|
|
//
|
|
// MXCSR = (39, "mxcsr"),
|
|
//
|
|
// ES = (40, "es"),
|
|
// CS = (41, "cs"),
|
|
// SS = (42, "ss"),
|
|
// DS = (43, "ds"),
|
|
// FS = (44, "fs"),
|
|
// GS = (45, "gs"),
|
|
//
|
|
// TR = (48, "tr"),
|
|
// LDTR = (49, "ldtr"),
|
|
//
|
|
// FS_BASE = (93, "fs.base"),
|
|
// GS_BASE = (94, "gs.base"),
|