| ... | ... | @@ -42,6 +42,11 @@ pub const Reloc = union(enum) { |
| 42 | 42 | /// To perform the reloc, write 32-bit signed little-endian integer |
| 43 | 43 | /// which is a relative jump, based on the address following the reloc. |
| 44 | 44 | rel32: usize, |
| 45 | /// A branch in the ARM instruction set |
| 46 | arm_branch: struct { |
| 47 | pos: usize, |
| 48 | cond: @import("codegen/arm.zig").Condition, |
| 49 | }, |
| 45 | 50 | }; |
| 46 | 51 | |
| 47 | 52 | pub const Result = union(enum) { |
| ... | ... | @@ -653,7 +658,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 653 | 658 | |
| 654 | 659 | const mcv = try self.genFuncInst(inst); |
| 655 | 660 | if (!inst.isUnused()) { |
| 656 | | log.debug("{*} => {}", .{ inst, mcv }); |
| 657 | 661 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| 658 | 662 | try branch.inst_table.putNoClobber(self.gpa, inst, mcv); |
| 659 | 663 | } |
| ... | ... | @@ -2016,6 +2020,27 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2016 | 2020 | self.code.items.len += 4; |
| 2017 | 2021 | break :reloc reloc; |
| 2018 | 2022 | }, |
| 2023 | .arm, .armeb => reloc: { |
| 2024 | const condition: Condition = switch (cond) { |
| 2025 | .register => |reg| blk: { |
| 2026 | // cmp reg, 1 |
| 2027 | // bne ... |
| 2028 | const op = Instruction.Operand.imm(1, 0); |
| 2029 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.cmp(.al, reg, op).toU32()); |
| 2030 | break :blk .ne; |
| 2031 | }, |
| 2032 | else => return self.fail(inst.base.src, "TODO implement condbr {} when condition is {}", .{ self.target.cpu.arch, @tagName(cond) }), |
| 2033 | }; |
| 2034 | |
| 2035 | const reloc = Reloc{ |
| 2036 | .arm_branch = .{ |
| 2037 | .pos = self.code.items.len, |
| 2038 | .cond = condition, |
| 2039 | }, |
| 2040 | }; |
| 2041 | try self.code.resize(self.code.items.len + 4); |
| 2042 | break :reloc reloc; |
| 2043 | }, |
| 2019 | 2044 | else => return self.fail(inst.base.src, "TODO implement condbr {}", .{self.target.cpu.arch}), |
| 2020 | 2045 | }; |
| 2021 | 2046 | |
| ... | ... | @@ -2225,6 +2250,19 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2225 | 2250 | return self.fail(src, "unable to perform relocation: jump too far", .{}); |
| 2226 | 2251 | mem.writeIntLittle(i32, self.code.items[pos..][0..4], s32_amt); |
| 2227 | 2252 | }, |
| 2253 | .arm_branch => |info| { |
| 2254 | switch (arch) { |
| 2255 | .arm, .armeb => { |
| 2256 | const amt = self.code.items.len - (info.pos + 4); |
| 2257 | if (math.cast(i26, amt)) |delta| { |
| 2258 | writeInt(u32, self.code.items[info.pos..][0..4], Instruction.b(info.cond, delta).toU32()); |
| 2259 | } else |_| { |
| 2260 | return self.fail(src, "TODO: enable larger branch offset", .{}); |
| 2261 | } |
| 2262 | }, |
| 2263 | else => unreachable, // attempting to perfrom an ARM relocation on a non-ARM target arch |
| 2264 | } |
| 2265 | }, |
| 2228 | 2266 | } |
| 2229 | 2267 | } |
| 2230 | 2268 | |
| ... | ... | @@ -2278,6 +2316,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2278 | 2316 | // Leave the jump offset undefined |
| 2279 | 2317 | block.codegen.relocs.appendAssumeCapacity(.{ .rel32 = self.code.items.len - 4 }); |
| 2280 | 2318 | }, |
| 2319 | .arm, .armeb => { |
| 2320 | try self.code.resize(self.code.items.len + 4); |
| 2321 | block.codegen.relocs.appendAssumeCapacity(.{ |
| 2322 | .arm_branch = .{ |
| 2323 | .pos = self.code.items.len - 4, |
| 2324 | .cond = .al, |
| 2325 | }, |
| 2326 | }); |
| 2327 | }, |
| 2281 | 2328 | else => return self.fail(src, "TODO implement brvoid for {}", .{self.target.cpu.arch}), |
| 2282 | 2329 | } |
| 2283 | 2330 | return .none; |