aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.zig
diff options
context:
space:
mode:
authorMathias Magnusson <mathias@magnusson.space>2025-07-01 23:06:06 +0200
committerMathias Magnusson <mathias@magnusson.space>2025-07-01 23:06:06 +0200
commit3959256af626292d50d5c05c63073ef28d760546 (patch)
treed223b13b4f7b375d26bbcef6b8ed0cbfdf22cb48 /src/codegen.zig
parentf5036d587fce5fd3e8199acbf3f186987147ec6a (diff)
downloadhuginn-3959256af626292d50d5c05c63073ef28d760546.tar.gz
make in-memory instruction a little nicer to work with
Diffstat (limited to 'src/codegen.zig')
-rw-r--r--src/codegen.zig68
1 files changed, 35 insertions, 33 deletions
diff --git a/src/codegen.zig b/src/codegen.zig
index 8c3f592..7ade3fd 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -22,7 +22,7 @@ const Register = enum(u5) {
};
/// TODO: Panic on calls that become reserved hints, e.g. addw with rd=x0
-const Instruction = packed union {
+const Instruction = union(enum) {
r: R,
i: I,
s: S,
@@ -199,7 +199,7 @@ const Instruction = packed union {
rd: Register,
funct3: u3,
rs1: Register,
- imm: u12,
+ imm: i12,
fn init(opcode: Opcode, rd: Register, funct3: u3, rs1: Register, imm: i12) Self {
return .{ .i = .{
@@ -207,7 +207,7 @@ const Instruction = packed union {
.rd = rd,
.funct3 = funct3,
.rs1 = rs1,
- .imm = @bitCast(imm),
+ .imm = imm,
} };
}
};
@@ -327,17 +327,16 @@ const Instruction = packed union {
funct3: u3,
rs1: Register,
rs2: Register,
- imm11_5: u7,
+ imm11_5: i7,
fn init(opcode: Opcode, funct3: u3, rs1: Register, rs2: Register, imm: i12) Self {
- const umm: u12 = @bitCast(imm);
return .{ .s = .{
.opcode = opcode,
- .imm4_0 = @truncate(umm),
+ .imm4_0 = @intCast(imm & 0xf),
.funct3 = funct3,
.rs1 = rs1,
.rs2 = rs2,
- .imm11_5 = @truncate(umm >> 5),
+ .imm11_5 = @intCast(imm >> 5),
} };
}
};
@@ -371,20 +370,19 @@ const Instruction = packed union {
rs1: Register,
rs2: Register,
imm10_5: u6,
- imm12: u1,
+ imm12: i1,
fn init(opcode: Opcode, funct3: u3, rs1: Register, rs2: Register, imm: i13) Self {
std.debug.assert(imm & 1 == 0);
- const umm: u13 = @bitCast(imm);
return .{ .b = .{
.opcode = opcode,
- .imm11 = @truncate(umm >> 11),
- .imm4_1 = @truncate(umm >> 1),
+ .imm11 = @intCast((imm >> 11) & 1),
+ .imm4_1 = @intCast((imm >> 1) & 0xf),
.funct3 = funct3,
.rs1 = rs1,
.rs2 = rs2,
- .imm10_5 = @truncate(umm >> 5),
- .imm12 = @truncate(umm >> 12),
+ .imm10_5 = @intCast((imm >> 5) & 0x3f),
+ .imm12 = @intCast(imm >> 12),
} };
}
};
@@ -440,13 +438,13 @@ const Instruction = packed union {
const U = packed struct(u32) {
opcode: Opcode,
rd: Register,
- imm12_31: u20,
+ imm12_31: i20,
fn init(opcode: Opcode, rd: Register, imm: i20) Self {
return .{ .u = .{
.opcode = opcode,
.rd = rd,
- .imm12_31 = @bitCast(imm),
+ .imm12_31 = imm,
} };
}
};
@@ -467,18 +465,17 @@ const Instruction = packed union {
imm12_19: u8,
imm11: u1,
imm1_10: u10,
- imm20: u1,
+ imm20: i1,
fn init(opcode: Opcode, rd: Register, imm: i21) Self {
std.debug.assert(imm & 1 == 0);
- const umm: u21 = @bitCast(imm);
return .{ .j = .{
.opcode = opcode,
.rd = rd,
- .imm12_19 = @truncate(umm >> 12),
- .imm11 = @truncate(umm >> 11),
- .imm1_10 = @truncate(umm >> 1),
- .imm20 = @intCast(umm >> 20),
+ .imm12_19 = @intCast((imm >> 12) & 0xff),
+ .imm11 = @intCast((imm >> 11) & 1),
+ .imm1_10 = @intCast((imm >> 1) & 0x3ff),
+ .imm20 = @intCast(imm >> 20),
} };
}
};
@@ -488,6 +485,12 @@ const Instruction = packed union {
return J.init(0b1101111, rd, imm);
}
+ fn encode(self: Self) u32 {
+ return switch (self) {
+ inline else => |s| @bitCast(s),
+ };
+ }
+
const Self = @This();
};
@@ -820,21 +823,20 @@ pub fn create_elf(allocator: Allocator, proc: compile.Procedure) ![]u8 {
// TODO: make this less sheiße
for (ctx.relocations.items) |relocation| {
const instr = &ctx.instructions.items[relocation.instr];
- const opcode: Instruction.Opcode = @truncate(@as(u32, @bitCast(instr.*)));
const target: isize = @intCast(ctx.block_starts.items[@intFromEnum(relocation.target)]);
const from: isize = @intCast(relocation.instr);
- switch (opcode) {
- 0b1101111 => {
- const jal: Instruction.J = instr.j;
- instr.* = .jal(jal.rd, @intCast((target - from) * 4));
+ switch (instr.*) {
+ .j => |j| {
+ if (j.opcode == 0b1101111) {
+ instr.* = .jal(j.rd, @intCast((target - from) * 4));
+ } else std.debug.panic("Not yet implemented instruction with relocation {}\n", .{instr});
},
- 0b1100011 => {
- const b: Instruction.B = instr.b;
- if (b.funct3 != 0)
- std.debug.panic("Not yet implemented instruction with relocation\n", .{});
- instr.* = .beq(b.rs1, b.rs2, @intCast((target - from) * 4));
+ .b => |b| {
+ if (b.opcode == 0b1100011 and b.funct3 == 0) {
+ instr.* = .beq(b.rs1, b.rs2, @intCast((target - from) * 4));
+ } else std.debug.panic("Not yet implemented instruction with relocation {}\n", .{instr});
},
- else => std.debug.panic("Not yet implemented instruction with relocation\n", .{}),
+ else => std.debug.panic("Not yet implemented instruction with relocation {}\n", .{instr}),
}
}
@@ -845,7 +847,7 @@ pub fn create_elf(allocator: Allocator, proc: compile.Procedure) ![]u8 {
try output_buffer.appendNTimes(undefined, @sizeOf(elf.Elf64_Ehdr) + @sizeOf(elf.Elf64_Phdr));
const output = output_buffer.writer();
for (ctx.instructions.items) |instr| {
- try output.writeInt(u32, @bitCast(instr), .little);
+ try output.writeInt(u32, instr.encode(), .little);
}
const base_addr = 0x10000000;