diff options
Diffstat (limited to 'src/codegen.zig')
| -rw-r--r-- | src/codegen.zig | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/src/codegen.zig b/src/codegen.zig index f978115ebc..a0e7968b97 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -42,6 +42,11 @@ pub const Reloc = union(enum) { /// To perform the reloc, write 32-bit signed little-endian integer /// which is a relative jump, based on the address following the reloc. rel32: usize, + /// A branch in the ARM instruction set + arm_branch: struct { + pos: usize, + cond: @import("codegen/arm.zig").Condition, + }, }; pub const Result = union(enum) { @@ -653,7 +658,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { const mcv = try self.genFuncInst(inst); if (!inst.isUnused()) { - log.debug("{*} => {}", .{ inst, mcv }); const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; try branch.inst_table.putNoClobber(self.gpa, inst, mcv); } @@ -2016,6 +2020,27 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { self.code.items.len += 4; break :reloc reloc; }, + .arm, .armeb => reloc: { + const condition: Condition = switch (cond) { + .register => |reg| blk: { + // cmp reg, 1 + // bne ... + const op = Instruction.Operand.imm(1, 0); + writeInt(u32, try self.code.addManyAsArray(4), Instruction.cmp(.al, reg, op).toU32()); + break :blk .ne; + }, + else => return self.fail(inst.base.src, "TODO implement condbr {} when condition is {}", .{ self.target.cpu.arch, @tagName(cond) }), + }; + + const reloc = Reloc{ + .arm_branch = .{ + .pos = self.code.items.len, + .cond = condition, + }, + }; + try self.code.resize(self.code.items.len + 4); + break :reloc reloc; + }, else => return self.fail(inst.base.src, "TODO implement condbr {}", .{self.target.cpu.arch}), }; @@ -2225,6 +2250,19 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { return self.fail(src, "unable to perform relocation: jump too far", .{}); mem.writeIntLittle(i32, self.code.items[pos..][0..4], s32_amt); }, + .arm_branch => |info| { + switch (arch) { + .arm, .armeb => { + const amt = self.code.items.len - (info.pos + 4); + if (math.cast(i26, amt)) |delta| { + writeInt(u32, self.code.items[info.pos..][0..4], Instruction.b(info.cond, delta).toU32()); + } else |_| { + return self.fail(src, "TODO: enable larger branch offset", .{}); + } + }, + else => unreachable, // attempting to perfrom an ARM relocation on a non-ARM target arch + } + }, } } @@ -2278,6 +2316,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { // Leave the jump offset undefined block.codegen.relocs.appendAssumeCapacity(.{ .rel32 = self.code.items.len - 4 }); }, + .arm, .armeb => { + try self.code.resize(self.code.items.len + 4); + block.codegen.relocs.appendAssumeCapacity(.{ + .arm_branch = .{ + .pos = self.code.items.len - 4, + .cond = .al, + }, + }); + }, else => return self.fail(src, "TODO implement brvoid for {}", .{self.target.cpu.arch}), } return .none; |
