From 648c840a6d4259e01b2a18b9fb55fd29aa3b65fb Mon Sep 17 00:00:00 2001 From: Grazfather Date: Fri, 20 Dec 2024 15:23:36 -0500 Subject: [PATCH] wip movrx --- .../rp2xxx/src/hal/pio/assembler/encoder.zig | 36 ++++++++- .../src/hal/pio/assembler/tokenizer.zig | 76 ++++++++++++++++++- 2 files changed, 105 insertions(+), 7 deletions(-) diff --git a/port/raspberrypi/rp2xxx/src/hal/pio/assembler/encoder.zig b/port/raspberrypi/rp2xxx/src/hal/pio/assembler/encoder.zig index 8f5ceac8..296277ad 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pio/assembler/encoder.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pio/assembler/encoder.zig @@ -355,7 +355,6 @@ pub fn Encoder(comptime cpu: CPU, comptime options: Options) type { .block = @intFromBool(pull.block), }, }, - // TODO: Make sure this is OK? We just added one more encoding .mov => |mov| .{ .mov = .{ .destination = mov.destination, @@ -363,6 +362,19 @@ pub fn Encoder(comptime cpu: CPU, comptime options: Options) type { .source = mov.source, }, }, + // NOTE: These instructions values only exist for RP2350 + .movtorx => |mov| .{ + .movtorx = .{ + .idxl = mov.idxl, + .idx = mov.idx, + }, + }, + .movfromrx => |mov| .{ + .movfromrx = .{ + .idxl = mov.idxl, + .idx = mov.idx, + }, + }, .irq => |irq| blk: { switch (cpu) { .RP2040 => { @@ -405,8 +417,10 @@ pub fn Encoder(comptime cpu: CPU, comptime options: Options) type { .wait => .wait, .in => .in, .out => .out, - .push => .push_pull, - .pull => .push_pull, + .push => .push_pull_mov_rx, + .pull => .push_pull_mov_rx, + .movtorx => .push_pull_mov_rx, + .movfromrx => .push_pull_mov_rx, .mov => .mov, .irq => .irq, .set => .set, @@ -566,6 +580,8 @@ pub fn Instruction(comptime cpu: CPU) type { push: Push, pull: Pull, mov: Mov, + movtorx: MovToRx, + movfromrx: MovFromRx, irq: Irq, set: Set, }; @@ -575,7 +591,7 @@ pub fn Instruction(comptime cpu: CPU) type { wait, in, out, - push_pull, + push_pull_mov_rx, mov, irq, set, @@ -638,6 +654,18 @@ pub fn Instruction(comptime cpu: CPU) type { }, }; + // RP2350 only, but we need them for the switch case + pub const MovToRx = packed struct(u8) { + _reserved0: u4 = 1, + idxl: bool, + idx: u3, + }; + pub const MovFromRx = packed struct(u8) { + _reserved0: u4 = 0, + idxl: bool, + idx: u3, + }; + pub const Set = packed struct(u8) { data: u5, destination: Token(cpu).Instruction.Set.Destination, diff --git a/port/raspberrypi/rp2xxx/src/hal/pio/assembler/tokenizer.zig b/port/raspberrypi/rp2xxx/src/hal/pio/assembler/tokenizer.zig index 8f5aa94c..454ffec2 100644 --- a/port/raspberrypi/rp2xxx/src/hal/pio/assembler/tokenizer.zig +++ b/port/raspberrypi/rp2xxx/src/hal/pio/assembler/tokenizer.zig @@ -736,8 +736,16 @@ pub fn Tokenizer(cpu: CPU) type { } fn get_mov(self: *Self, diags: *?Diagnostics) TokenizeError!Token(cpu).Instruction.Payload { - const dest_str = (try self.get_arg(diags)) orelse return error.MissingArg; - const dest_lower = try lowercase_bounded(256, dest_str); + // Peek so that we can unwind for the mov_rx case + const dest_str = try self.peek_arg(diags) orelse return error.MissingArg; + const dest_lower = try lowercase_bounded(256, dest_str.str); + // If the destination is rxfifo_ or rxfifoy, then it's a mov (to) rx instruction + if (cpu == .RP2350 and std.mem.startsWith(u8, dest_lower.slice(), "rxfifo")) { + return try self.get_movrx(diags); + } + + self.consume_peek(dest_str); + const destination = std.meta.stringToEnum(Token(cpu).Instruction.Mov.Destination, dest_lower.slice()) orelse return error.InvalidDestination; const second = try self.get_arg(diags) orelse return error.MissingArg; @@ -781,6 +789,58 @@ pub fn Tokenizer(cpu: CPU) type { }; } + fn get_movrx(self: *Self, diags: *?Diagnostics) TokenizeError!Token(cpu).Instruction.Payload { + const dest_str = (try self.get_arg(diags)) orelse return error.MissingArg; + const dest_lower = try lowercase_bounded(256, dest_str); + const source_str = (try self.get_arg(diags)) orelse return error.MissingArg; + const source_lower = try lowercase_bounded(256, source_str); + if (std.mem.eql(u8, dest_lower.slice(), "rxfifoy")) { + // MOV (to RX) + // Second arg must be isr + if (!std.mem.eql(u8, source_lower.slice(), "isr")) + return error.InvalidSource; + + return Token(cpu).Instruction.Payload{ + .movtorx = .{ + .idxl = true, + .idx = 0, + }, + }; + } else if (std.mem.startsWith(u8, dest_lower.slice(), "rxfifo")) { + // MOV (to RX) + // TODO: Parse out the index + const idx = 0; + return Token(cpu).Instruction.Payload{ + .movtorx = .{ + .idxl = false, + .idx = idx, + }, + }; + } else if (std.mem.eql(u8, dest_lower.slice(), "osr")) { + // MOV (from RX) + var idxl: bool = false; + var idx: u3 = 0; + if (std.mem.eql(u8, source_lower.slice(), "rxfifoy")) { + idxl = true; + idx = 0; + } else if (std.mem.startsWith(u8, source_lower.slice(), "rxfifo")) { + // TODO: Parse out the index + idxl = false; + idx = 0; + } else { + return error.InvalidSource; + } + return Token(cpu).Instruction.Payload{ + .movfromrx = .{ + .idxl = idxl, + .idx = idx, + }, + }; + } else { + return error.InvalidDestination; + } + } + fn get_irq(self: *Self, diags: *?Diagnostics) TokenizeError!Token(cpu).Instruction.Payload { const first = (try self.get_arg(diags)) orelse return error.MissingArg; @@ -1059,6 +1119,8 @@ pub fn Token(comptime cpu: CPU) type { push: Push, pull: Pull, mov: Mov, + movtorx: if (cpu == .RP2350) MovToRx else noreturn, + movfromrx: if (cpu == .RP2350) MovFromRx else noreturn, irq: Irq, set: Set, }; @@ -1140,7 +1202,6 @@ pub fn Token(comptime cpu: CPU) type { ifempty: bool, }; - // TODO: Add mov to RX for rp2350 pub const Mov = struct { destination: Destination, operation: Operation, @@ -1185,6 +1246,15 @@ pub fn Token(comptime cpu: CPU) type { }; }; + pub const MovToRx = struct { + idxl: bool, + idx: u3, + }; + pub const MovFromRx = struct { + idxl: bool, + idx: u3, + }; + pub const Irq = switch (cpu) { .RP2040 => struct { clear: bool,