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(...@@ -76,8 +76,8 @@ pub fn generateSymbol(
76 switch (bin_file.options.target.cpu.arch) {76 switch (bin_file.options.target.cpu.arch) {
77 .wasm32 => unreachable, // has its own code path77 .wasm32 => unreachable, // has its own code path
78 .wasm64 => unreachable, // has its own code path78 .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),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),80 .armeb => return Function(.armeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
81 //.aarch64 => return Function(.aarch64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),81 //.aarch64 => return Function(.aarch64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
82 //.aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),82 //.aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),
83 //.aarch64_32 => return Function(.aarch64_32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),83 //.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 {...@@ -1270,8 +1270,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1270 var instr = Instruction{ .condition = .always, .input0 = .zero, .input1 = .zero, .modify_flags = false, .output = .discard, .command = .undefined1 };1270 var instr = Instruction{ .condition = .always, .input0 = .zero, .input1 = .zero, .modify_flags = false, .output = .discard, .command = .undefined1 };
1271 mem.writeIntLittle(u16, self.code.items[self.code.items.len - 2 ..][0..2], @bitCast(u16, instr));1271 mem.writeIntLittle(u16, self.code.items[self.code.items.len - 2 ..][0..2], @bitCast(u16, instr));
1272 },1272 },
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 },
1273 else => return self.fail(src, "TODO implement @breakpoint() for {}", .{self.target.cpu.arch}),1279 else => return self.fail(src, "TODO implement @breakpoint() for {}", .{self.target.cpu.arch}),
1274 }1280 }
1275 return .none;1281 return .none;
1276 }1282 }
12771283
...@@ -2373,6 +2379,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2373,6 +2379,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2373 .riscv64 => @import("codegen/riscv64.zig"),2379 .riscv64 => @import("codegen/riscv64.zig"),
2374 .spu_2 => @import("codegen/spu-mk2.zig"),2380 .spu_2 => @import("codegen/spu-mk2.zig"),
2375 .arm => @import("codegen/arm.zig"),2381 .arm => @import("codegen/arm.zig"),
2382 .armeb => @import("codegen/arm.zig"),
2376 else => struct {2383 else => struct {
2377 pub const Register = enum {2384 pub const Register = enum {
2378 dummy,2385 dummy,
src-self-hosted/codegen/arm.zig+39
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const DW = std.dwarf;
2const testing = std.testing;3const testing = std.testing;
34
4/// The condition field specifies the flags neccessary for an5/// The condition field specifies the flags neccessary for an
...@@ -93,6 +94,18 @@ pub const Register = enum(u5) {...@@ -93,6 +94,18 @@ pub const Register = enum(u5) {
93 pub fn id(self: Register) u4 {94 pub fn id(self: Register) u4 {
94 return @truncate(u4, @enumToInt(self));95 return @truncate(u4, @enumToInt(self));
95 }96 }
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 }
96};109};
97110
98test "Register.id" {111test "Register.id" {
...@@ -149,6 +162,12 @@ pub const Instruction = union(enum) {...@@ -149,6 +162,12 @@ pub const Instruction = union(enum) {
149 fixed: u4 = 0b1111,162 fixed: u4 = 0b1111,
150 cond: u4,163 cond: u4,
151 },164 },
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
153 /// Represents the possible operations which can be performed by a172 /// Represents the possible operations which can be performed by a
154 /// DataProcessing instruction173 /// DataProcessing instruction
...@@ -326,6 +345,7 @@ pub const Instruction = union(enum) {...@@ -326,6 +345,7 @@ pub const Instruction = union(enum) {
326 .Branch => |v| @bitCast(u32, v),345 .Branch => |v| @bitCast(u32, v),
327 .BranchExchange => |v| @bitCast(u32, v),346 .BranchExchange => |v| @bitCast(u32, v),
328 .SoftwareInterrupt => |v| @bitCast(u32, v),347 .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),
329 };349 };
330 }350 }
331351
...@@ -408,6 +428,15 @@ pub const Instruction = union(enum) {...@@ -408,6 +428,15 @@ pub const Instruction = union(enum) {
408 };428 };
409 }429 }
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
411 // Public functions replicating assembler syntax as closely as440 // Public functions replicating assembler syntax as closely as
412 // possible441 // possible
413442
...@@ -512,6 +541,12 @@ pub const Instruction = union(enum) {...@@ -512,6 +541,12 @@ pub const Instruction = union(enum) {
512 pub fn swi(cond: Condition, comment: u24) Instruction {541 pub fn swi(cond: Condition, comment: u24) Instruction {
513 return softwareInterrupt(cond, comment);542 return softwareInterrupt(cond, comment);
514 }543 }
544
545 // Breakpoint
546
547 pub fn bkpt(imm: u16) Instruction {
548 return breakpoint(imm);
549 }
515};550};
516551
517test "serialize instructions" {552test "serialize instructions" {
...@@ -557,6 +592,10 @@ test "serialize instructions" {...@@ -557,6 +592,10 @@ test "serialize instructions" {
557 .inst = Instruction.swi(.al, 0),592 .inst = Instruction.swi(.al, 0),
558 .expected = 0b1110_1111_0000_0000_0000_0000_0000_0000,593 .expected = 0b1110_1111_0000_0000_0000_0000_0000_0000,
559 },594 },
595 .{ // bkpt #42
596 .inst = Instruction.bkpt(42),
597 .expected = 0b1110_0001_0010_000000000010_0111_1010,
598 },
560 };599 };
561600
562 for (testcases) |case| {601 for (testcases) |case| {