aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/x86.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen/x86.zig')
-rw-r--r--src/codegen/x86.zig123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/codegen/x86.zig b/src/codegen/x86.zig
new file mode 100644
index 0000000000..fdad4e56db
--- /dev/null
+++ b/src/codegen/x86.zig
@@ -0,0 +1,123 @@
+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"),