diff options
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | src/codegen.zig | 51 | ||||
-rw-r--r-- | src/main.zig | 23 |
3 files changed, 67 insertions, 9 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..313e155 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +- <https://five-embeddev.com/riscv-user-isa-manual/Priv-v1.12/rv32.html#rv32> +- <https://files.magnusson.space/random/riscv-instruction-sheet-3.pdf> diff --git a/src/codegen.zig b/src/codegen.zig new file mode 100644 index 0000000..da1acd2 --- /dev/null +++ b/src/codegen.zig @@ -0,0 +1,51 @@ +const std = @import("std"); +const elf = std.elf; +const Allocator = std.mem.Allocator; +const root = @import("root"); +const Block = root.Block; + +pub fn create_elf(allocator: Allocator, block: Block) ![]u8 { + _ = block; + + const base_addr = 0x10000000; + const elf_header: elf.Elf64_Ehdr = .{ + .e_ident = elf.MAGIC.* ++ [_]u8{ + elf.ELFCLASS64, // EI_CLASS + elf.ELFDATA2LSB, // EI_DATA + 1, // EI_VERSION + @intFromEnum(elf.OSABI.NONE), // EI_OSABI + 0, // EI_ABIVERSION + } ++ [1]u8{0} ** 7, // EI_PAD + .e_type = .EXEC, + .e_machine = elf.EM.RISCV, + .e_version = 1, + .e_entry = base_addr + @sizeOf(elf.Elf64_Ehdr) + @sizeOf(elf.Elf64_Phdr), // we place the code directly after the headers + .e_phoff = @sizeOf(elf.Elf64_Ehdr), // we place the program header(s) directly after the elf header + .e_shoff = 0, + .e_flags = 0, // ? + .e_ehsize = @sizeOf(elf.Elf64_Ehdr), + .e_phentsize = @sizeOf(elf.Elf64_Phdr), + .e_phnum = 1, + .e_shentsize = @sizeOf(elf.Elf64_Shdr), + .e_shnum = 0, + .e_shstrndx = 0, + }; + const program_header: elf.Elf64_Phdr = .{ + .p_type = elf.PT_LOAD, + .p_flags = elf.PF_R | elf.PF_X, + .p_offset = 0, + .p_vaddr = base_addr, + .p_paddr = base_addr, + .p_filesz = @sizeOf(elf.Elf64_Ehdr) + @sizeOf(elf.Elf64_Phdr) + 40, + .p_memsz = @sizeOf(elf.Elf64_Ehdr) + @sizeOf(elf.Elf64_Phdr) + 40, + .p_align = 0x1000, + }; + + var output_buffer: std.ArrayList(u8) = .init(allocator); + errdefer output_buffer.deinit(); + const output = output_buffer.writer(); + try output.writeAll(std.mem.asBytes(&elf_header)); + try output.writeAll(std.mem.asBytes(&program_header)); + for (0..10) |_| try output.writeAll(&std.mem.toBytes(@as(u32, 0x13))); + return output_buffer.toOwnedSlice(); +} diff --git a/src/main.zig b/src/main.zig index d938d9b..a7874d8 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2,19 +2,23 @@ const std = @import("std"); const parse = @import("./parse.zig"); const peek = @import("./peek.zig"); const compile = @import("./compile.zig"); +const codegen = @import("./codegen.zig"); pub const peekable = peek.peekable; pub const Peekable = peek.Peekable; pub const Expr = parse.Expr; pub const Lexer = @import("./lexer.zig"); +pub const Block = compile.Block; pub fn main() !void { var arena: std.heap.ArenaAllocator = .init(std.heap.smp_allocator); defer arena.deinit(); const allocator = arena.allocator(); - var bw = std.io.bufferedWriter(std.io.getStdOut().writer()); - const stdout = bw.writer(); + var args = std.process.args(); + _ = args.next(); + const out_file = if (args.next()) |path| try std.fs.cwd().createFile(path, .{}) else std.io.getStdOut(); + const output = out_file.writer(); // var br = std.io.bufferedReader(std.io.getStdIn().reader()); // const stdin = br.reader(); @@ -33,22 +37,23 @@ pub fn main() !void { // var lexer = Lexer{ .source = source }; // while (true) { // const token = lexer.next().?; - // try stdout.print("{}\n", .{token}); + // std.debug.print("{}\n", .{token}); // if (token.type == .Eof) break; // } - // try stdout.print("\n", .{}); + // std.debug.print("\n", .{}); var lexer = peekable(Lexer{ .source = source }); const expr = try parse.expression(allocator, &lexer); - try stdout.print("{}\n", .{expr}); + std.debug.print("{}\n", .{expr}); if (lexer.next()) |token| if (token.type != .eof) { - try stdout.print("Unexpected token {}, expected end of file\n", .{token}); + std.debug.print("Unexpected token {}, expected end of file\n", .{token}); }; const block = try compile.compile(allocator, expr); for (block.instrs) |instr| { - try stdout.print("{}\n", .{instr}); + std.debug.print("{}\n", .{instr}); } - - try bw.flush(); // Don't forget to flush! + const elf = try codegen.create_elf(allocator, block); + try output.writeAll(elf); + // try stdout.print("{x}\n", .{elf}); } test { |