| author | |
| committer | |
| log | 88c8ff6e374334e538a686781d608c1b204aeb45 |
| tree | bf0c2c108b4c2a79ac6b8819c1ba4053c4236508 |
| parent | e198eec76a478fa9d1cb7b6d7488e273a0d15ff1 |
6 files changed, 104 insertions(+), 91 deletions(-)
src-self-hosted/backend.zig deleted-2| ... | ... | @@ -1,2 +0,0 @@ |
| 1 | pub const x86_64 = @import("backend/x86_64.zig"); | |
| 2 | pub const x86 = @import("backend/x86.zig"); |
src-self-hosted/backend/x86.zig deleted-30| ... | ... | @@ -1,30 +0,0 @@ |
| 1 | // zig fmt: off | |
| 2 | pub const Register = enum(u8) { | |
| 3 | // 0 through 7, 32-bit registers. id is int value | |
| 4 | eax, ecx, edx, ebx, esp, ebp, esi, edi, | |
| 5 | ||
| 6 | // 8-15, 16-bit registers. id is int value - 8. | |
| 7 | ax, cx, dx, bx, sp, bp, si, di, | |
| 8 | ||
| 9 | // 16-23, 8-bit registers. id is int value - 16. | |
| 10 | al, bl, cl, dl, ah, ch, dh, bh, | |
| 11 | ||
| 12 | /// Returns the bit-width of the register. | |
| 13 | pub fn size(self: @This()) u7 { | |
| 14 | return switch (@enumToInt(self)) { | |
| 15 | 0...7 => 32, | |
| 16 | 8...15 => 16, | |
| 17 | 16...23 => 8, | |
| 18 | else => unreachable, | |
| 19 | }; | |
| 20 | } | |
| 21 | ||
| 22 | /// Returns the register's id. This is used in practically every opcode the | |
| 23 | /// x86 has. It is embedded in some instructions, such as the `B8 +rd` move | |
| 24 | /// instruction, and is used in the R/M byte. | |
| 25 | pub fn id(self: @This()) u3 { | |
| 26 | return @truncate(u3, @enumToInt(self)); | |
| 27 | } | |
| 28 | }; | |
| 29 | ||
| 30 | // zig fmt: on |
src-self-hosted/backend/x86_64.zig deleted-53| ... | ... | @@ -1,53 +0,0 @@ |
| 1 | // zig fmt: off | |
| 2 | pub const Register = enum(u8) { | |
| 3 | // 0 through 15, 64-bit registers. 8-15 are extended. | |
| 4 | // id is just the int value. | |
| 5 | rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, | |
| 6 | r8, r9, r10, r11, r12, r13, r14, r15, | |
| 7 | ||
| 8 | // 16 through 31, 32-bit registers. 24-31 are extended. | |
| 9 | // id is int value - 16. | |
| 10 | eax, ecx, edx, ebx, esp, ebp, esi, edi, | |
| 11 | r8d, r9d, r10d, r11d, r12d, r13d, r14d, r15d, | |
| 12 | ||
| 13 | // 32-47, 16-bit registers. 40-47 are extended. | |
| 14 | // id is int value - 32. | |
| 15 | ax, cx, dx, bx, sp, bp, si, di, | |
| 16 | r8w, r9w, r10w, r11w, r12w, r13w, r14w, r15w, | |
| 17 | ||
| 18 | // 48-63, 8-bit registers. 56-63 are extended. | |
| 19 | // id is int value - 48. | |
| 20 | al, bl, cl, dl, ah, ch, dh, bh, | |
| 21 | r8b, r9b, r10b, r11b, r12b, r13b, r14b, r15b, | |
| 22 | ||
| 23 | /// Returns the bit-width of the register. | |
| 24 | pub fn size(self: @This()) u7 { | |
| 25 | return switch (@enumToInt(self)) { | |
| 26 | 0...15 => 64, | |
| 27 | 16...31 => 32, | |
| 28 | 32...47 => 16, | |
| 29 | 48...64 => 8, | |
| 30 | else => unreachable, | |
| 31 | }; | |
| 32 | } | |
| 33 | ||
| 34 | /// Returns whether the register is *extended*. Extended registers are the | |
| 35 | /// new registers added with amd64, r8 through r15. This also includes any | |
| 36 | /// other variant of access to those registers, such as r8b, r15d, and so | |
| 37 | /// on. This is needed because access to these registers requires special | |
| 38 | /// handling via the REX prefix, via the B or R bits, depending on context. | |
| 39 | pub fn isExtended(self: @This()) bool { | |
| 40 | return @enumToInt(self) & 0x08 != 0; | |
| 41 | } | |
| 42 | ||
| 43 | /// This returns the 4-bit register ID, which is used in practically every | |
| 44 | /// opcode. Note that bit 3 (the highest bit) is *never* used directly in | |
| 45 | /// an instruction (@see isExtended), and requires special handling. The | |
| 46 | /// lower three bits are often embedded directly in instructions (such as | |
| 47 | /// the B8 variant of moves), or used in R/M bytes. | |
| 48 | pub fn id(self: @This()) u4 { | |
| 49 | return @truncate(u4, @enumToInt(self)); | |
| 50 | } | |
| 51 | }; | |
| 52 | ||
| 53 | // zig fmt: on |
src-self-hosted/codegen.zig+21-6| ... | ... | @@ -11,8 +11,6 @@ const ErrorMsg = Module.ErrorMsg; |
| 11 | 11 | const Target = std.Target; |
| 12 | 12 | const Allocator = mem.Allocator; |
| 13 | 13 | |
| 14 | const Backend = @import("backend.zig"); | |
| 15 | ||
| 16 | 14 | pub const Result = union(enum) { |
| 17 | 15 | /// The `code` parameter passed to `generateSymbol` has the value appended. |
| 18 | 16 | appended: void, |
| ... | ... | @@ -194,14 +192,28 @@ const Function = struct { |
| 194 | 192 | }, |
| 195 | 193 | else => return self.fail(src, "TODO implement @breakpoint() for {}", .{self.target.cpu.arch}), |
| 196 | 194 | } |
| 197 | return .unreach; | |
| 195 | return .none; | |
| 198 | 196 | } |
| 199 | 197 | |
| 200 | 198 | fn genCall(self: *Function, inst: *ir.Inst.Call) !MCValue { |
| 199 | if (inst.args.func.cast(ir.Inst.Constant)) |func_inst| { | |
| 200 | if (inst.args.args.len != 0) { | |
| 201 | return self.fail(inst.base.src, "TODO implement call with more than 0 parameters", .{}); | |
| 202 | } | |
| 203 | ||
| 204 | if (func_inst.val.cast(Value.Payload.Function)) |func_val| { | |
| 205 | const func = func_val.func; | |
| 206 | return self.fail(inst.base.src, "TODO implement calling function", .{}); | |
| 207 | } else { | |
| 208 | return self.fail(inst.base.src, "TODO implement calling weird function values", .{}); | |
| 209 | } | |
| 210 | } else { | |
| 211 | return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{}); | |
| 212 | } | |
| 213 | ||
| 201 | 214 | switch (self.target.cpu.arch) { |
| 202 | 215 | else => return self.fail(inst.base.src, "TODO implement call for {}", .{self.target.cpu.arch}), |
| 203 | 216 | } |
| 204 | return .unreach; | |
| 205 | 217 | } |
| 206 | 218 | |
| 207 | 219 | fn genRet(self: *Function, inst: *ir.Inst.Ret) !MCValue { |
| ... | ... | @@ -589,10 +601,13 @@ const Function = struct { |
| 589 | 601 | } |
| 590 | 602 | }; |
| 591 | 603 | |
| 604 | const x86_64 = @import("codegen/x86_64.zig"); | |
| 605 | const x86 = @import("codegen/x86.zig"); | |
| 606 | ||
| 592 | 607 | fn Reg(comptime arch: Target.Cpu.Arch) type { |
| 593 | 608 | return switch (arch) { |
| 594 | .i386 => Backend.x86.Register, | |
| 595 | .x86_64 => Backend.x86_64.Register, | |
| 609 | .i386 => x86.Register, | |
| 610 | .x86_64 => x86_64.Register, | |
| 596 | 611 | else => @compileError("TODO add more register enums"), |
| 597 | 612 | }; |
| 598 | 613 | } |
src-self-hosted/codegen/x86.zig created+30| ... | ... | @@ -0,0 +1,30 @@ |
| 1 | // zig fmt: off | |
| 2 | pub const Register = enum(u8) { | |
| 3 | // 0 through 7, 32-bit registers. id is int value | |
| 4 | eax, ecx, edx, ebx, esp, ebp, esi, edi, | |
| 5 | ||
| 6 | // 8-15, 16-bit registers. id is int value - 8. | |
| 7 | ax, cx, dx, bx, sp, bp, si, di, | |
| 8 | ||
| 9 | // 16-23, 8-bit registers. id is int value - 16. | |
| 10 | al, bl, cl, dl, ah, ch, dh, bh, | |
| 11 | ||
| 12 | /// Returns the bit-width of the register. | |
| 13 | pub fn size(self: @This()) u7 { | |
| 14 | return switch (@enumToInt(self)) { | |
| 15 | 0...7 => 32, | |
| 16 | 8...15 => 16, | |
| 17 | 16...23 => 8, | |
| 18 | else => unreachable, | |
| 19 | }; | |
| 20 | } | |
| 21 | ||
| 22 | /// Returns the register's id. This is used in practically every opcode the | |
| 23 | /// x86 has. It is embedded in some instructions, such as the `B8 +rd` move | |
| 24 | /// instruction, and is used in the R/M byte. | |
| 25 | pub fn id(self: @This()) u3 { | |
| 26 | return @truncate(u3, @enumToInt(self)); | |
| 27 | } | |
| 28 | }; | |
| 29 | ||
| 30 | // zig fmt: on |
src-self-hosted/codegen/x86_64.zig created+53| ... | ... | @@ -0,0 +1,53 @@ |
| 1 | // zig fmt: off | |
| 2 | pub const Register = enum(u8) { | |
| 3 | // 0 through 15, 64-bit registers. 8-15 are extended. | |
| 4 | // id is just the int value. | |
| 5 | rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, | |
| 6 | r8, r9, r10, r11, r12, r13, r14, r15, | |
| 7 | ||
| 8 | // 16 through 31, 32-bit registers. 24-31 are extended. | |
| 9 | // id is int value - 16. | |
| 10 | eax, ecx, edx, ebx, esp, ebp, esi, edi, | |
| 11 | r8d, r9d, r10d, r11d, r12d, r13d, r14d, r15d, | |
| 12 | ||
| 13 | // 32-47, 16-bit registers. 40-47 are extended. | |
| 14 | // id is int value - 32. | |
| 15 | ax, cx, dx, bx, sp, bp, si, di, | |
| 16 | r8w, r9w, r10w, r11w, r12w, r13w, r14w, r15w, | |
| 17 | ||
| 18 | // 48-63, 8-bit registers. 56-63 are extended. | |
| 19 | // id is int value - 48. | |
| 20 | al, bl, cl, dl, ah, ch, dh, bh, | |
| 21 | r8b, r9b, r10b, r11b, r12b, r13b, r14b, r15b, | |
| 22 | ||
| 23 | /// Returns the bit-width of the register. | |
| 24 | pub fn size(self: @This()) u7 { | |
| 25 | return switch (@enumToInt(self)) { | |
| 26 | 0...15 => 64, | |
| 27 | 16...31 => 32, | |
| 28 | 32...47 => 16, | |
| 29 | 48...64 => 8, | |
| 30 | else => unreachable, | |
| 31 | }; | |
| 32 | } | |
| 33 | ||
| 34 | /// Returns whether the register is *extended*. Extended registers are the | |
| 35 | /// new registers added with amd64, r8 through r15. This also includes any | |
| 36 | /// other variant of access to those registers, such as r8b, r15d, and so | |
| 37 | /// on. This is needed because access to these registers requires special | |
| 38 | /// handling via the REX prefix, via the B or R bits, depending on context. | |
| 39 | pub fn isExtended(self: @This()) bool { | |
| 40 | return @enumToInt(self) & 0x08 != 0; | |
| 41 | } | |
| 42 | ||
| 43 | /// This returns the 4-bit register ID, which is used in practically every | |
| 44 | /// opcode. Note that bit 3 (the highest bit) is *never* used directly in | |
| 45 | /// an instruction (@see isExtended), and requires special handling. The | |
| 46 | /// lower three bits are often embedded directly in instructions (such as | |
| 47 | /// the B8 variant of moves), or used in R/M bytes. | |
| 48 | pub fn id(self: @This()) u4 { | |
| 49 | return @truncate(u4, @enumToInt(self)); | |
| 50 | } | |
| 51 | }; | |
| 52 | ||
| 53 | // zig fmt: on |