Commit 1c53c07053

joachimschmidt557 <joachim.schmidt557@outlook.com>
2020-08-20 23:09:46
stage2: Implement genBreakpoint for ARM
1 parent f31cee5
Changed files (2)
src-self-hosted
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| {
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,