From 1c53c070535c519cbdc39a2094a24723f5245799 Mon Sep 17 00:00:00 2001 From: joachimschmidt557 Date: Thu, 20 Aug 2020 23:09:46 +0200 Subject: [PATCH] stage2: Implement genBreakpoint for ARM --- src-self-hosted/codegen.zig | 13 ++++++++--- src-self-hosted/codegen/arm.zig | 39 +++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src-self-hosted/codegen.zig b/src-self-hosted/codegen.zig index a1145a6c52..1e26f4ccf2 100644 --- a/src-self-hosted/codegen.zig +++ b/src-self-hosted/codegen.zig @@ -76,8 +76,8 @@ pub fn generateSymbol( switch (bin_file.options.target.cpu.arch) { .wasm32 => unreachable, // has its own code path .wasm64 => unreachable, // has its own code path - //.arm => return Function(.arm).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs), - //.armeb => return Function(.armeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs), + .arm => return Function(.arm).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs), + .armeb => return Function(.armeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs), //.aarch64 => return Function(.aarch64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs), //.aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs), //.aarch64_32 => return Function(.aarch64_32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs), @@ -1270,8 +1270,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { var instr = Instruction{ .condition = .always, .input0 = .zero, .input1 = .zero, .modify_flags = false, .output = .discard, .command = .undefined1 }; mem.writeIntLittle(u16, self.code.items[self.code.items.len - 2 ..][0..2], @bitCast(u16, instr)); }, + .arm => { + mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.bkpt(0).toU32()); + }, + .armeb => { + mem.writeIntBig(u32, try self.code.addManyAsArray(4), Instruction.bkpt(0).toU32()); + }, else => return self.fail(src, "TODO implement @breakpoint() for {}", .{self.target.cpu.arch}), - } + } return .none; } @@ -2373,6 +2379,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { .riscv64 => @import("codegen/riscv64.zig"), .spu_2 => @import("codegen/spu-mk2.zig"), .arm => @import("codegen/arm.zig"), + .armeb => @import("codegen/arm.zig"), else => struct { pub const Register = enum { dummy, diff --git a/src-self-hosted/codegen/arm.zig b/src-self-hosted/codegen/arm.zig index 7674e8af33..f509d4b6e4 100644 --- a/src-self-hosted/codegen/arm.zig +++ b/src-self-hosted/codegen/arm.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const DW = std.dwarf; const testing = std.testing; /// The condition field specifies the flags neccessary for an @@ -93,6 +94,18 @@ pub const Register = enum(u5) { pub fn id(self: Register) u4 { return @truncate(u4, @enumToInt(self)); } + + /// Returns the index into `callee_preserved_regs`. + pub fn allocIndex(self: Register) ?u4 { + inline for (callee_preserved_regs) |cpreg, i| { + if (self.id() == cpreg.id()) return i; + } + return null; + } + + pub fn dwarfLocOp(self: Register) u8 { + return @as(u8, self.id()) + DW.OP_reg0; + } }; test "Register.id" { @@ -149,6 +162,12 @@ pub const Instruction = union(enum) { fixed: u4 = 0b1111, cond: u4, }, + Breakpoint: packed struct { + imm4: u4, + fixed_1: u4 = 0b0111, + imm12: u12, + fixed_2_and_cond: u12 = 0b1110_0001_0010, + }, /// Represents the possible operations which can be performed by a /// DataProcessing instruction @@ -326,6 +345,7 @@ pub const Instruction = union(enum) { .Branch => |v| @bitCast(u32, v), .BranchExchange => |v| @bitCast(u32, v), .SoftwareInterrupt => |v| @bitCast(u32, v), + .Breakpoint => |v| @intCast(u32, v.imm4) | (@intCast(u32, v.fixed_1) << 4) | (@intCast(u32, v.imm12) << 8) | (@intCast(u32, v.fixed_2_and_cond) << 20), }; } @@ -408,6 +428,15 @@ pub const Instruction = union(enum) { }; } + fn breakpoint(imm: u16) Instruction { + return Instruction{ + .Breakpoint = .{ + .imm12 = @truncate(u12, imm >> 4), + .imm4 = @truncate(u4, imm), + }, + }; + } + // Public functions replicating assembler syntax as closely as // possible @@ -512,6 +541,12 @@ pub const Instruction = union(enum) { pub fn swi(cond: Condition, comment: u24) Instruction { return softwareInterrupt(cond, comment); } + + // Breakpoint + + pub fn bkpt(imm: u16) Instruction { + return breakpoint(imm); + } }; test "serialize instructions" { @@ -557,6 +592,10 @@ test "serialize instructions" { .inst = Instruction.swi(.al, 0), .expected = 0b1110_1111_0000_0000_0000_0000_0000_0000, }, + .{ // bkpt #42 + .inst = Instruction.bkpt(42), + .expected = 0b1110_0001_0010_000000000010_0111_1010, + }, }; for (testcases) |case| {