authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2020-08-20 23:09:46+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2020-08-23 22:29:00+02:00
log1c53c070535c519cbdc39a2094a24723f5245799
tree3eda4394f30e67286e229c43d956e1dcb2cd9585
parentf31cee5393bbfd29883a7b253cd518db145b8b19

stage2: Implement genBreakpoint for ARM


2 files changed, 49 insertions(+), 3 deletions(-)

src-self-hosted/codegen.zig+10-3
......@@ -76,8 +76,8 @@ pub fn generateSymbol(
7676 switch (bin_file.options.target.cpu.arch) {
7777 .wasm32 => unreachable, // has its own code path
7878 .wasm64 => unreachable, // has its own code path
79 //.arm => return Function(.arm).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
80 //.armeb => return Function(.armeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
79 .arm => return Function(.arm).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
80 .armeb => return Function(.armeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
8181 //.aarch64 => return Function(.aarch64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
8282 //.aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
8383 //.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 {
12701270 var instr = Instruction{ .condition = .always, .input0 = .zero, .input1 = .zero, .modify_flags = false, .output = .discard, .command = .undefined1 };
12711271 mem.writeIntLittle(u16, self.code.items[self.code.items.len - 2 ..][0..2], @bitCast(u16, instr));
12721272 },
1273 .arm => {
1274 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.bkpt(0).toU32());
1275 },
1276 .armeb => {
1277 mem.writeIntBig(u32, try self.code.addManyAsArray(4), Instruction.bkpt(0).toU32());
1278 },
12731279 else => return self.fail(src, "TODO implement @breakpoint() for {}", .{self.target.cpu.arch}),
1274 }
1280 }
12751281 return .none;
12761282 }
12771283
......@@ -2373,6 +2379,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
23732379 .riscv64 => @import("codegen/riscv64.zig"),
23742380 .spu_2 => @import("codegen/spu-mk2.zig"),
23752381 .arm => @import("codegen/arm.zig"),
2382 .armeb => @import("codegen/arm.zig"),
23762383 else => struct {
23772384 pub const Register = enum {
23782385 dummy,
src-self-hosted/codegen/arm.zig+39
......@@ -1,4 +1,5 @@
11const std = @import("std");
2const DW = std.dwarf;
23const testing = std.testing;
34
45/// The condition field specifies the flags neccessary for an
......@@ -93,6 +94,18 @@ pub const Register = enum(u5) {
9394 pub fn id(self: Register) u4 {
9495 return @truncate(u4, @enumToInt(self));
9596 }
97
98 /// Returns the index into `callee_preserved_regs`.
99 pub fn allocIndex(self: Register) ?u4 {
100 inline for (callee_preserved_regs) |cpreg, i| {
101 if (self.id() == cpreg.id()) return i;
102 }
103 return null;
104 }
105
106 pub fn dwarfLocOp(self: Register) u8 {
107 return @as(u8, self.id()) + DW.OP_reg0;
108 }
96109};
97110
98111test "Register.id" {
......@@ -149,6 +162,12 @@ pub const Instruction = union(enum) {
149162 fixed: u4 = 0b1111,
150163 cond: u4,
151164 },
165 Breakpoint: packed struct {
166 imm4: u4,
167 fixed_1: u4 = 0b0111,
168 imm12: u12,
169 fixed_2_and_cond: u12 = 0b1110_0001_0010,
170 },
152171
153172 /// Represents the possible operations which can be performed by a
154173 /// DataProcessing instruction
......@@ -326,6 +345,7 @@ pub const Instruction = union(enum) {
326345 .Branch => |v| @bitCast(u32, v),
327346 .BranchExchange => |v| @bitCast(u32, v),
328347 .SoftwareInterrupt => |v| @bitCast(u32, v),
348 .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),
329349 };
330350 }
331351
......@@ -408,6 +428,15 @@ pub const Instruction = union(enum) {
408428 };
409429 }
410430
431 fn breakpoint(imm: u16) Instruction {
432 return Instruction{
433 .Breakpoint = .{
434 .imm12 = @truncate(u12, imm >> 4),
435 .imm4 = @truncate(u4, imm),
436 },
437 };
438 }
439
411440 // Public functions replicating assembler syntax as closely as
412441 // possible
413442
......@@ -512,6 +541,12 @@ pub const Instruction = union(enum) {
512541 pub fn swi(cond: Condition, comment: u24) Instruction {
513542 return softwareInterrupt(cond, comment);
514543 }
544
545 // Breakpoint
546
547 pub fn bkpt(imm: u16) Instruction {
548 return breakpoint(imm);
549 }
515550};
516551
517552test "serialize instructions" {
......@@ -557,6 +592,10 @@ test "serialize instructions" {
557592 .inst = Instruction.swi(.al, 0),
558593 .expected = 0b1110_1111_0000_0000_0000_0000_0000_0000,
559594 },
595 .{ // bkpt #42
596 .inst = Instruction.bkpt(42),
597 .expected = 0b1110_0001_0010_000000000010_0111_1010,
598 },
560599 };
561600
562601 for (testcases) |case| {