diff --git a/pio-parser/src/lib.rs b/pio-parser/src/lib.rs index b8e2ffb..21120af 100644 --- a/pio-parser/src/lib.rs +++ b/pio-parser/src/lib.rs @@ -4,8 +4,9 @@ #![allow(clippy::upper_case_acronyms)] use pio::{ - InSource, Instruction, InstructionOperands, JmpCondition, MovDestination, MovOperation, - MovSource, OutDestination, ProgramWithDefines, SetDestination, WaitSource, + InSource, Instruction, InstructionOperands, IrqIndexMode, JmpCondition, MovDestination, + MovOperation, MovRxIndex, MovSource, OutDestination, ProgramWithDefines, SetDestination, + WaitSource, }; use std::collections::HashMap; @@ -28,7 +29,7 @@ pub(crate) enum Value<'input> { Rev(Box>), } -impl<'i> Value<'i> { +impl Value<'_> { fn reify(&self, state: &ProgramState) -> i32 { match self { Value::I32(v) => *v, @@ -76,7 +77,7 @@ pub(crate) struct ParsedInstruction<'input> { delay: Value<'input>, } -impl<'i> ParsedInstruction<'i> { +impl ParsedInstruction<'_> { fn reify(&self, state: &ProgramState) -> Instruction { Instruction { operands: self.operands.reify(state), @@ -86,6 +87,90 @@ impl<'i> ParsedInstruction<'i> { } } +#[derive(Clone, Copy, Debug)] +pub(crate) enum ParsedMovDestination { + PINS, + X, + Y, + PINDIRS, + EXEC, + PC, + ISR, + OSR, + RXFIFOY, + RXFIFO0, + RXFIFO1, + RXFIFO2, + RXFIFO3, +} + +#[derive(Debug)] +enum MovDestInternal { + Mov(MovDestination), + Fifo(MovRxIndex), +} + +impl From for MovDestInternal { + fn from(value: ParsedMovDestination) -> Self { + match value { + ParsedMovDestination::PINS => MovDestInternal::Mov(MovDestination::PINS), + ParsedMovDestination::X => MovDestInternal::Mov(MovDestination::X), + ParsedMovDestination::Y => MovDestInternal::Mov(MovDestination::Y), + ParsedMovDestination::PINDIRS => MovDestInternal::Mov(MovDestination::PINDIRS), + ParsedMovDestination::EXEC => MovDestInternal::Mov(MovDestination::EXEC), + ParsedMovDestination::PC => MovDestInternal::Mov(MovDestination::PC), + ParsedMovDestination::ISR => MovDestInternal::Mov(MovDestination::ISR), + ParsedMovDestination::OSR => MovDestInternal::Mov(MovDestination::OSR), + ParsedMovDestination::RXFIFOY => MovDestInternal::Fifo(MovRxIndex::RXFIFOY), + ParsedMovDestination::RXFIFO0 => MovDestInternal::Fifo(MovRxIndex::RXFIFO0), + ParsedMovDestination::RXFIFO1 => MovDestInternal::Fifo(MovRxIndex::RXFIFO1), + ParsedMovDestination::RXFIFO2 => MovDestInternal::Fifo(MovRxIndex::RXFIFO2), + ParsedMovDestination::RXFIFO3 => MovDestInternal::Fifo(MovRxIndex::RXFIFO3), + } + } +} + +#[derive(Clone, Copy, Debug)] +pub(crate) enum ParsedMovSource { + PINS, + X, + Y, + NULL, + STATUS, + ISR, + OSR, + RXFIFOY, + RXFIFO0, + RXFIFO1, + RXFIFO2, + RXFIFO3, +} + +#[derive(Debug)] +enum MovSrcInternal { + Mov(MovSource), + Fifo(MovRxIndex), +} + +impl From for MovSrcInternal { + fn from(value: ParsedMovSource) -> Self { + match value { + ParsedMovSource::PINS => MovSrcInternal::Mov(MovSource::PINS), + ParsedMovSource::X => MovSrcInternal::Mov(MovSource::X), + ParsedMovSource::Y => MovSrcInternal::Mov(MovSource::Y), + ParsedMovSource::NULL => MovSrcInternal::Mov(MovSource::NULL), + ParsedMovSource::STATUS => MovSrcInternal::Mov(MovSource::STATUS), + ParsedMovSource::ISR => MovSrcInternal::Mov(MovSource::ISR), + ParsedMovSource::OSR => MovSrcInternal::Mov(MovSource::OSR), + ParsedMovSource::RXFIFOY => MovSrcInternal::Fifo(MovRxIndex::RXFIFOY), + ParsedMovSource::RXFIFO0 => MovSrcInternal::Fifo(MovRxIndex::RXFIFO0), + ParsedMovSource::RXFIFO1 => MovSrcInternal::Fifo(MovRxIndex::RXFIFO1), + ParsedMovSource::RXFIFO2 => MovSrcInternal::Fifo(MovRxIndex::RXFIFO2), + ParsedMovSource::RXFIFO3 => MovSrcInternal::Fifo(MovRxIndex::RXFIFO3), + } + } +} + #[derive(Debug)] pub(crate) enum ParsedOperands<'input> { JMP { @@ -115,15 +200,15 @@ pub(crate) enum ParsedOperands<'input> { block: bool, }, MOV { - destination: MovDestination, + destination: ParsedMovDestination, op: MovOperation, - source: MovSource, + source: ParsedMovSource, }, IRQ { clear: bool, wait: bool, index: Value<'input>, - relative: bool, + index_mode: IrqIndexMode, }, SET { destination: SetDestination, @@ -131,7 +216,7 @@ pub(crate) enum ParsedOperands<'input> { }, } -impl<'i> ParsedOperands<'i> { +impl ParsedOperands<'_> { fn reify(&self, state: &ProgramState) -> InstructionOperands { match self { ParsedOperands::JMP { condition, address } => InstructionOperands::JMP { @@ -172,21 +257,35 @@ impl<'i> ParsedOperands<'i> { destination, op, source, - } => InstructionOperands::MOV { - destination: *destination, - op: *op, - source: *source, - }, + } => { + let source_internal = (*source).into(); + let dest_internal = (*destination).into(); + match (source_internal, dest_internal) { + (MovSrcInternal::Mov(MovSource::ISR), MovDestInternal::Fifo(fifo_index)) => { + InstructionOperands::MOVTORX { fifo_index } + } + ( + MovSrcInternal::Fifo(fifo_index), + MovDestInternal::Mov(MovDestination::OSR), + ) => InstructionOperands::MOVFROMRX { fifo_index }, + (MovSrcInternal::Mov(s), MovDestInternal::Mov(d)) => InstructionOperands::MOV { + destination: d, + op: *op, + source: s, + }, + (d, s) => panic!("Illegal Mov src/dest combination: {:?} {:?}", d, s), + } + } ParsedOperands::IRQ { clear, wait, index, - relative, + index_mode, } => InstructionOperands::IRQ { clear: *clear, wait: *wait, index: index.reify(state) as u8, - relative: *relative, + index_mode: *index_mode, }, ParsedOperands::SET { destination, data } => InstructionOperands::SET { destination: *destination, @@ -426,6 +525,41 @@ fn test() { ); } +#[test] +fn test_rp2350() { + let p = Parser::<32>::parse_program( + " + label: + mov osr, rxfifo[0] + mov rxfifo[1], isr + mov pins, isr + mov osr, x + jmp label + ", + ) + .unwrap(); + + assert_eq!( + &p.program.code[..], + &[ + // LABEL: + 0b100_00000_1001_1_000, // MOV OSR, RXFIFO0 + 0b100_00000_0001_1_001, // MOV RXFIFO1, ISR + 0b101_00000_000_00_110, // MOV PINS, ISR + 0b101_00000_111_00_001, // MOV OSR, X + 0b000_00000_000_00000, // JMP LABEL + ] + ); + assert_eq!(p.program.origin, None); + assert_eq!( + p.program.wrap, + pio::Wrap { + source: 4, + target: 0, + } + ); +} + #[test] fn test_side_set() { let p = Parser::<32>::parse_program( diff --git a/pio-parser/src/pio.lalrpop b/pio-parser/src/pio.lalrpop index ed099cc..a2b0c93 100644 --- a/pio-parser/src/pio.lalrpop +++ b/pio-parser/src/pio.lalrpop @@ -10,6 +10,7 @@ use ::pio::{ MovOperation, MovSource, SetDestination, + IrqIndexMode, }; use crate::{ Line, @@ -17,6 +18,8 @@ use crate::{ ParsedDirective, ParsedInstruction, ParsedOperands, + ParsedMovSource, + ParsedMovDestination, }; grammar(); @@ -139,9 +142,9 @@ Instruction: ParsedInstruction<'input> = { BaseInstruction: ParsedOperands<'input> = { "nop" => ParsedOperands::MOV { - destination: MovDestination::Y, + destination: ParsedMovDestination::Y, op: MovOperation::None, - source: MovSource::Y, + source: ParsedMovSource::Y, }, "jmp" ","? => ParsedOperands::JMP { condition: match c { @@ -178,7 +181,7 @@ BaseInstruction: ParsedOperands<'input> = { None => true, }, }, - "mov" ","? => ParsedOperands::MOV { + "mov" ","? => ParsedOperands::MOV { destination: d, op: match o { Some(o) => o, @@ -186,7 +189,7 @@ BaseInstruction: ParsedOperands<'input> = { }, source: s, }, - "irq" => ParsedOperands::IRQ { + "irq" => ParsedOperands::IRQ { clear: match m { Some(m) => m.0, None => false, @@ -196,7 +199,10 @@ BaseInstruction: ParsedOperands<'input> = { None => false, }, index: v, - relative: r.is_some(), + index_mode: match r { + Some(m) => m, + None => IrqIndexMode::DIRECT + } }, "set" ","? => ParsedOperands::SET { destination: d, @@ -245,14 +251,20 @@ ShouldBlock: bool = { "noblock" => false, }; -MovDestination: MovDestination = { - "pins" => MovDestination::PINS, - "x" => MovDestination::X, - "y" => MovDestination::Y, - "exec" => MovDestination::EXEC, - "pc" => MovDestination::PC, - "isr" => MovDestination::ISR, - "osr" => MovDestination::OSR, +ParsedMovDestination: ParsedMovDestination = { + "pins" => ParsedMovDestination::PINS, + "x" => ParsedMovDestination::X, + "y" => ParsedMovDestination::Y, + "pindirs" => ParsedMovDestination::PINDIRS, + "exec" => ParsedMovDestination::EXEC, + "pc" => ParsedMovDestination::PC, + "isr" => ParsedMovDestination::ISR, + "osr" => ParsedMovDestination::OSR, + "rxfifo[y]" => ParsedMovDestination::RXFIFOY, + "rxfifo[0]" => ParsedMovDestination::RXFIFO0, + "rxfifo[1]" => ParsedMovDestination::RXFIFO1, + "rxfifo[2]" => ParsedMovDestination::RXFIFO2, + "rxfifo[3]" => ParsedMovDestination::RXFIFO3, }; MovOperation: MovOperation = { @@ -261,14 +273,19 @@ MovOperation: MovOperation = { "::" => MovOperation::BitReverse, }; -MovSource: MovSource = { - "pins" => MovSource::PINS, - "x" => MovSource::X, - "y" => MovSource::Y, - "null" => MovSource::NULL, - "status" => MovSource::STATUS, - "isr" => MovSource::ISR, - "osr" => MovSource::OSR, +ParsedMovSource: ParsedMovSource = { + "pins" => ParsedMovSource::PINS, + "x" => ParsedMovSource::X, + "y" => ParsedMovSource::Y, + "null" => ParsedMovSource::NULL, + "status" => ParsedMovSource::STATUS, + "isr" => ParsedMovSource::ISR, + "osr" => ParsedMovSource::OSR, + "rxfifo[y]" => ParsedMovSource::RXFIFOY, + "rxfifo[0]" => ParsedMovSource::RXFIFO0, + "rxfifo[1]" => ParsedMovSource::RXFIFO1, + "rxfifo[2]" => ParsedMovSource::RXFIFO2, + "rxfifo[3]" => ParsedMovSource::RXFIFO3, }; IrqModifier: (bool, bool) = { @@ -278,6 +295,12 @@ IrqModifier: (bool, bool) = { "clear" => (true, false), }; +IrqIndexMode: IrqIndexMode = { + "prev" => IrqIndexMode::PREV, + "rel" => IrqIndexMode::REL, + "next" => IrqIndexMode::NEXT, +} + SetDestination: SetDestination = { "pins" => SetDestination::PINS, "x" => SetDestination::X, diff --git a/pio-proc/src/lib.rs b/pio-proc/src/lib.rs index 2feafa5..851b9ef 100644 --- a/pio-proc/src/lib.rs +++ b/pio-proc/src/lib.rs @@ -349,6 +349,9 @@ fn to_codegen( ) .parse() .unwrap(); + let version: proc_macro2::TokenStream = format!("::pio::PioVersion::{:?}", program.version) + .parse() + .unwrap(); let defines_struct: proc_macro2::TokenStream = format!( " struct ExpandedDefines {{ @@ -387,6 +390,7 @@ fn to_codegen( origin: #origin, wrap: #wrap, side_set: #side_set, + version: #version, }, public_defines: #defines_init, } diff --git a/src/lib.rs b/src/lib.rs index b06e260..05052fc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,13 +42,23 @@ pub use arrayvec::ArrayVec; use core::convert::TryFrom; use num_enum::TryFromPrimitive; -/// Maximum program size of RP2040 chip, in bytes. +/// Maximum program size of RP2040 and RP235x chips, in bytes. /// /// See Chapter 3, Figure 38 for reference of the value. pub const RP2040_MAX_PROGRAM_SIZE: usize = 32; +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[non_exhaustive] +/// PIO version +pub enum PioVersion { + /// Pio programs compatible with both the RP2040 and RP235x + V0, + /// Pio programs compatible with the RP235x + V1, +} + #[repr(u8)] -#[derive(Debug, Clone, Copy, TryFromPrimitive)] +#[derive(Debug, Clone, Copy, TryFromPrimitive, PartialEq, Eq)] pub enum JmpCondition { /// Always Always = 0b000, @@ -74,11 +84,11 @@ pub enum WaitSource { GPIO = 0b00, PIN = 0b01, IRQ = 0b10, - // RESERVED = 0b11, + JMPPIN = 0b11, } #[repr(u8)] -#[derive(Debug, Clone, Copy, TryFromPrimitive)] +#[derive(Debug, Clone, Copy, TryFromPrimitive, PartialEq, Eq)] pub enum InSource { PINS = 0b000, X = 0b001, @@ -91,7 +101,7 @@ pub enum InSource { } #[repr(u8)] -#[derive(Debug, Clone, Copy, TryFromPrimitive)] +#[derive(Debug, Clone, Copy, TryFromPrimitive, PartialEq, Eq)] pub enum OutDestination { PINS = 0b000, X = 0b001, @@ -104,12 +114,12 @@ pub enum OutDestination { } #[repr(u8)] -#[derive(Debug, Clone, Copy, TryFromPrimitive)] +#[derive(Debug, Clone, Copy, TryFromPrimitive, PartialEq, Eq)] pub enum MovDestination { PINS = 0b000, X = 0b001, Y = 0b010, - // RESERVED = 0b011, + PINDIRS = 0b011, EXEC = 0b100, PC = 0b101, ISR = 0b110, @@ -117,7 +127,7 @@ pub enum MovDestination { } #[repr(u8)] -#[derive(Debug, Clone, Copy, TryFromPrimitive)] +#[derive(Debug, Clone, Copy, TryFromPrimitive, PartialEq, Eq)] pub enum MovOperation { None = 0b00, Invert = 0b01, @@ -126,7 +136,7 @@ pub enum MovOperation { } #[repr(u8)] -#[derive(Debug, Clone, Copy, TryFromPrimitive)] +#[derive(Debug, Clone, Copy, TryFromPrimitive, PartialEq, Eq)] pub enum MovSource { PINS = 0b000, X = 0b001, @@ -139,7 +149,17 @@ pub enum MovSource { } #[repr(u8)] -#[derive(Debug, Clone, Copy, TryFromPrimitive)] +#[derive(Debug, Clone, Copy, TryFromPrimitive, PartialEq, Eq)] +pub enum MovRxIndex { + RXFIFOY = 0b0000, + RXFIFO0 = 0b1000, + RXFIFO1 = 0b1001, + RXFIFO2 = 0b1010, + RXFIFO3 = 0b1011, +} + +#[repr(u8)] +#[derive(Debug, Clone, Copy, TryFromPrimitive, PartialEq, Eq)] pub enum SetDestination { PINS = 0b000, X = 0b001, @@ -151,6 +171,15 @@ pub enum SetDestination { // RESERVED = 0b111, } +#[repr(u8)] +#[derive(Debug, Clone, Copy, TryFromPrimitive, PartialEq, Eq)] +pub enum IrqIndexMode { + DIRECT = 0b00, + PREV = 0b01, + REL = 0b10, + NEXT = 0b11, +} + #[derive(Debug, Clone, Copy)] pub enum InstructionOperands { JMP { @@ -186,11 +215,17 @@ pub enum InstructionOperands { op: MovOperation, source: MovSource, }, + MOVTORX { + fifo_index: MovRxIndex, + }, + MOVFROMRX { + fifo_index: MovRxIndex, + }, IRQ { clear: bool, wait: bool, index: u8, - relative: bool, + index_mode: IrqIndexMode, }, SET { destination: SetDestination, @@ -208,6 +243,8 @@ impl InstructionOperands { InstructionOperands::PUSH { .. } => 0b100, InstructionOperands::PULL { .. } => 0b100, InstructionOperands::MOV { .. } => 0b101, + InstructionOperands::MOVTORX { .. } => 0b100, + InstructionOperands::MOVFROMRX { .. } => 0b100, InstructionOperands::IRQ { .. } => 0b110, InstructionOperands::SET { .. } => 0b111, } @@ -259,18 +296,20 @@ impl InstructionOperands { op, source, } => (*destination as u8, (*op as u8) << 3 | (*source as u8)), + InstructionOperands::MOVTORX { fifo_index } => (0, 1 << 4 | *fifo_index as u8), + InstructionOperands::MOVFROMRX { fifo_index } => (0b100, 1 << 4 | *fifo_index as u8), InstructionOperands::IRQ { clear, wait, index, - relative, + index_mode, } => { if *index > 7 { panic!("invalid interrupt flags"); } ( (*clear as u8) << 1 | (*wait as u8), - *index | (if *relative { 0b10000 } else { 0 }), + *index | (*index_mode as u8) << 3, ) } InstructionOperands::SET { destination, data } => { @@ -299,6 +338,7 @@ impl InstructionOperands { let discrim = instruction >> 13; let o0 = ((instruction >> 5) & 0b111) as u8; let o1 = (instruction & 0b11111) as u8; + match discrim { 0b000 => JmpCondition::try_from(o0) .ok() @@ -335,20 +375,32 @@ impl InstructionOperands { }) } 0b100 => { - let if_flag = o0 & 0b010 != 0; - let block = o0 & 0b001 != 0; - if o1 != 0 { - None - } else if o0 & 0b100 == 0 { + let p_o0 = ((instruction >> 4) & 0b1111) as u8; + + let if_flag = p_o0 & 0b0100 != 0; + let block = p_o0 & 0b0010 != 0; + + let index = MovRxIndex::try_from((instruction & 0b1111) as u8); + if p_o0 & 0b1001 == 0b1000 { + Some(InstructionOperands::PULL { + if_empty: if_flag, + block, + }) + } else if p_o0 & 0b1001 == 0b0000 { Some(InstructionOperands::PUSH { if_full: if_flag, block, }) - } else { - Some(InstructionOperands::PULL { - if_empty: if_flag, - block, + } else if p_o0 == 0b1001 { + Some(InstructionOperands::MOVFROMRX { + fifo_index: index.ok()?, }) + } else if p_o0 == 0b0001 { + Some(InstructionOperands::MOVTORX { + fifo_index: index.ok()?, + }) + } else { + None } } 0b101 => match ( @@ -365,11 +417,12 @@ impl InstructionOperands { }, 0b110 => { if o0 & 0b100 == 0 { + let index_mode = IrqIndexMode::try_from((o1 >> 3) & 0b11); Some(InstructionOperands::IRQ { clear: o0 & 0b010 != 0, wait: o0 & 0b001 != 0, - index: o1 & 0b01111, - relative: o1 & 0b10000 != 0, + index: o1 & 0b00111, + index_mode: index_mode.ok()?, }) } else { None @@ -559,6 +612,35 @@ impl Assembler { .collect() } + /// Check the program for instructions and operands available only on the RP2350. + pub fn version(&self) -> PioVersion { + for instr in &self.instructions { + let opr = instr.operands; + match opr { + InstructionOperands::MOVFROMRX { .. } => return PioVersion::V1, + InstructionOperands::MOVTORX { .. } => return PioVersion::V1, + InstructionOperands::MOV { destination, .. } => { + if destination == MovDestination::PINDIRS { + return PioVersion::V1; + } + } + InstructionOperands::WAIT { source, .. } => { + if source == WaitSource::JMPPIN { + return PioVersion::V1; + } + } + InstructionOperands::IRQ { index_mode, .. } => { + if index_mode == IrqIndexMode::PREV || index_mode == IrqIndexMode::NEXT { + return PioVersion::V1; + } + } + _ => (), + } + } + + PioVersion::V0 + } + /// Assemble the program into [`Program`]. /// /// The program contains the instructions and side-set info set. You can directly compile into a program with @@ -566,6 +648,7 @@ impl Assembler { /// [`Program::set_wrap`]. pub fn assemble_program(self) -> Program { let side_set = self.side_set; + let version = self.version(); let code = self.assemble(); let wrap = Wrap { source: (code.len() - 1) as u8, @@ -577,6 +660,7 @@ impl Assembler { origin: None, side_set, wrap, + version, } } @@ -743,14 +827,32 @@ impl Assembler { } ); + instr!( + /// Emit a `mov to rx` instruction. + mov_to_rx(self, fifo_index: MovRxIndex) { + InstructionOperands::MOVTORX { + fifo_index + } + } + ); + + instr!( + /// Emit a `mov from rx` instruction. + mov_from_rx(self, fifo_index: MovRxIndex) { + InstructionOperands::MOVFROMRX { + fifo_index + } + } + ); + instr!( /// Emit an `irq` instruction using `clear` and `wait` with `index` which may be `relative`. - irq(self, clear: bool, wait: bool, index: u8, relative: bool) { + irq(self, clear: bool, wait: bool, index: u8, index_mode: IrqIndexMode) { InstructionOperands::IRQ { clear, wait, index, - relative, + index_mode } } ); @@ -812,6 +914,8 @@ pub struct Program { pub wrap: Wrap, /// Side-set info for this program. pub side_set: SideSet, + /// Pio Version required for this program. + pub version: PioVersion, } impl Program { @@ -926,7 +1030,7 @@ fn test_assemble_program_default_wrap() { } macro_rules! instr_test { - ($name:ident ( $( $v:expr ),* ) , $expected:expr, $side_set:expr) => { + ($name:ident ( $( $v:expr ),* ) , $expected:expr, $side_set:expr, $version:expr) => { paste::paste! { #[test] fn [< test _ $name _ $expected >]() { @@ -936,6 +1040,9 @@ macro_rules! instr_test { a.$name( $( $v ),* ); + + assert_eq!(a.version(), $version); + let instr = a.assemble()[0]; if instr != expected { panic!("assertion failure: (left == right)\nleft: {:#016b}\nright: {:#016b}", instr, expected); @@ -950,24 +1057,42 @@ macro_rules! instr_test { } }; - ($name:ident ( $( $v:expr ),* ) , $b:expr) => { - instr_test!( $name ( $( $v ),* ), $b, SideSet::new(false, 0, false) ); + ($name:ident ( $( $v:expr ),* ) , $b:expr, $version:expr) => { + instr_test!( $name ( $( $v ),* ), $b, SideSet::new(false, 0, false), $version); }; } -instr_test!(wait(0, WaitSource::IRQ, 2, false), 0b001_00000_010_00010); -instr_test!(wait(1, WaitSource::IRQ, 7, false), 0b001_00000_110_00111); -instr_test!(wait(1, WaitSource::GPIO, 16, false), 0b001_00000_100_10000); +instr_test!( + wait(0, WaitSource::IRQ, 2, false), + 0b001_00000_010_00010, + PioVersion::V0 +); +instr_test!( + wait(1, WaitSource::IRQ, 7, false), + 0b001_00000_110_00111, + PioVersion::V0 +); +instr_test!( + wait(1, WaitSource::GPIO, 16, false), + 0b001_00000_100_10000, + PioVersion::V0 +); instr_test!( wait_with_delay(0, WaitSource::IRQ, 2, false, 30), - 0b001_11110_010_00010 + 0b001_11110_010_00010, + PioVersion::V0 ); instr_test!( wait_with_side_set(0, WaitSource::IRQ, 2, false, 0b10101), 0b001_10101_010_00010, - SideSet::new(false, 5, false) + SideSet::new(false, 5, false), + PioVersion::V0 +); +instr_test!( + wait(0, WaitSource::IRQ, 2, true), + 0b001_00000_010_10010, + PioVersion::V0 ); -instr_test!(wait(0, WaitSource::IRQ, 2, true), 0b001_00000_010_10010); #[test] #[should_panic] @@ -977,11 +1102,19 @@ fn test_wait_relative_not_used_on_irq() { a.assemble_program(); } -instr_test!(r#in(InSource::Y, 10), 0b010_00000_010_01010); -instr_test!(r#in(InSource::Y, 32), 0b010_00000_010_00000); +instr_test!(r#in(InSource::Y, 10), 0b010_00000_010_01010, PioVersion::V0); +instr_test!(r#in(InSource::Y, 32), 0b010_00000_010_00000, PioVersion::V0); -instr_test!(out(OutDestination::Y, 10), 0b011_00000_010_01010); -instr_test!(out(OutDestination::Y, 32), 0b011_00000_010_00000); +instr_test!( + out(OutDestination::Y, 10), + 0b011_00000_010_01010, + PioVersion::V0 +); +instr_test!( + out(OutDestination::Y, 32), + 0b011_00000_010_00000, + PioVersion::V0 +); #[test] #[should_panic(expected = "bit_count must be from 1 to 32")] @@ -1015,11 +1148,11 @@ fn test_out_bit_width_exceeds_max_should_panic() { a.assemble_program(); } -instr_test!(push(true, false), 0b100_00000_010_00000); -instr_test!(push(false, true), 0b100_00000_001_00000); +instr_test!(push(true, false), 0b100_00000_010_00000, PioVersion::V0); +instr_test!(push(false, true), 0b100_00000_001_00000, PioVersion::V0); -instr_test!(pull(true, false), 0b100_00000_110_00000); -instr_test!(pull(false, true), 0b100_00000_101_00000); +instr_test!(pull(true, false), 0b100_00000_110_00000, PioVersion::V0); +instr_test!(pull(false, true), 0b100_00000_101_00000, PioVersion::V0); instr_test!( mov( @@ -1027,13 +1160,70 @@ instr_test!( MovOperation::BitReverse, MovSource::STATUS ), - 0b101_00000_010_10101 + 0b101_00000_010_10101, + PioVersion::V0 +); + +instr_test!( + irq(true, false, 0b11, IrqIndexMode::DIRECT), + 0b110_00000_010_00_011, + PioVersion::V0 +); +instr_test!( + irq(false, true, 0b111, IrqIndexMode::REL), + 0b110_00000_001_10_111, + PioVersion::V0 +); +instr_test!( + irq(true, false, 0b1, IrqIndexMode::PREV), + 0b110_00000_010_01_001, + PioVersion::V1 +); +instr_test!( + irq(false, true, 0b101, IrqIndexMode::NEXT), + 0b110_00000_001_11_101, + PioVersion::V1 +); + +instr_test!( + set(SetDestination::Y, 10), + 0b111_00000_010_01010, + PioVersion::V0 ); -instr_test!(irq(true, false, 0b11, false), 0b110_00000_010_00011); -instr_test!(irq(false, true, 0b111, true), 0b110_00000_001_10111); +instr_test!( + mov(MovDestination::PINDIRS, MovOperation::None, MovSource::X), + 0b101_00000_0110_0001, + PioVersion::V1 +); -instr_test!(set(SetDestination::Y, 10), 0b111_00000_010_01010); +instr_test!( + wait(0, WaitSource::JMPPIN, 0, false), + 0b001_00000_0110_0000, + PioVersion::V1 +); + +instr_test!( + mov_to_rx(MovRxIndex::RXFIFO3), + 0b100_00000_0001_1011, + PioVersion::V1 +); +instr_test!( + mov_to_rx(MovRxIndex::RXFIFOY), + 0b100_00000_0001_0000, + PioVersion::V1 +); + +instr_test!( + mov_from_rx(MovRxIndex::RXFIFO3), + 0b100_00000_1001_1011, + PioVersion::V1 +); +instr_test!( + mov_from_rx(MovRxIndex::RXFIFOY), + 0b100_00000_1001_0000, + PioVersion::V1 +); /// This block ensures that README.md is checked when `cargo test` is run. #[cfg(doctest)]