| 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,8 +11,6 @@ const ErrorMsg = Module.ErrorMsg; |
| 11 | const Target = std.Target; | 11 | const Target = std.Target; |
| 12 | const Allocator = mem.Allocator; | 12 | const Allocator = mem.Allocator; |
| 13 | 13 | ||
| 14 | const Backend = @import("backend.zig"); | ||
| 15 | |||
| 16 | pub const Result = union(enum) { | 14 | pub const Result = union(enum) { |
| 17 | /// The `code` parameter passed to `generateSymbol` has the value appended. | 15 | /// The `code` parameter passed to `generateSymbol` has the value appended. |
| 18 | appended: void, | 16 | appended: void, |
| ... | @@ -194,14 +192,28 @@ const Function = struct { | ... | @@ -194,14 +192,28 @@ const Function = struct { |
| 194 | }, | 192 | }, |
| 195 | else => return self.fail(src, "TODO implement @breakpoint() for {}", .{self.target.cpu.arch}), | 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 | fn genCall(self: *Function, inst: *ir.Inst.Call) !MCValue { | 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 | switch (self.target.cpu.arch) { | 214 | switch (self.target.cpu.arch) { |
| 202 | else => return self.fail(inst.base.src, "TODO implement call for {}", .{self.target.cpu.arch}), | 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 | fn genRet(self: *Function, inst: *ir.Inst.Ret) !MCValue { | 219 | fn genRet(self: *Function, inst: *ir.Inst.Ret) !MCValue { |
| ... | @@ -589,10 +601,13 @@ const Function = struct { | ... | @@ -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 | fn Reg(comptime arch: Target.Cpu.Arch) type { | 607 | fn Reg(comptime arch: Target.Cpu.Arch) type { |
| 593 | return switch (arch) { | 608 | return switch (arch) { |
| 594 | .i386 => Backend.x86.Register, | 609 | .i386 => x86.Register, |
| 595 | .x86_64 => Backend.x86_64.Register, | 610 | .x86_64 => x86_64.Register, |
| 596 | else => @compileError("TODO add more register enums"), | 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 | ||