Fix assembly of irq & mov rxfifo[] instructions to match sdk pioasm

This commit is contained in:
Jeff Epler 2024-09-13 16:32:12 -05:00
parent 89fc1a125a
commit 679feb8e21
2 changed files with 55 additions and 38 deletions

View file

@ -234,7 +234,7 @@ class Program: # pylint: disable=too-few-public-methods
max_delay = 2 ** (5 - sideset_count - sideset_enable) - 1
assembled = []
for line in instructions:
for line in instructions: # pylint: disable=too-many-nested-blocks
instruction = splitter(line.strip())
delay = 0
if (
@ -299,21 +299,32 @@ class Program: # pylint: disable=too-few-public-methods
assembled[-1] |= num
assembled[-1] |= 0b11 << 5 # JMPPIN wait source
else:
idx = 3
assembled[-1] |= WAIT_SOURCES.index(instruction[2]) << 5
num = int(instruction[3], 0)
if not 0 <= num <= 31:
raise RuntimeError("Wait num out of range")
assembled[-1] |= num
# The flag index is decoded in the same way as the IRQ
# index field, decoding down from the two MSBs
if instruction[-1] == "next":
if source == "irq":
if instruction[idx] == "next":
require_version(1, "wait irq next")
assembled[-1] |= 0b11000
elif instruction[-1] == "prev":
idx += 1
elif instruction[idx] == "prev":
require_version(1, "wait irq prev")
assembled[-1] |= 0b01000
elif instruction[-1] == "rel":
idx += 1
limit = 8
# The flag index is decoded in the same way as the IRQ
# index field, decoding down from the two MSBs
if instruction[-1] == "rel":
if assembled[-1] & 0b11000:
raise RuntimeError("cannot use next/prev with rel")
assembled[-1] |= 0b10000
else:
limit = 32
num = int_in_range(
instruction[idx], 0, limit, "wait {instruction[2]}"
)
assembled[-1] |= num
elif instruction[0] == "in":
# instr delay src count
assembled.append(0b010_00000_000_00000)
@ -352,15 +363,15 @@ class Program: # pylint: disable=too-few-public-methods
elif instruction[0] == "mov":
# instr delay dst op src
if instruction[1].startswith("rxfifo["): # mov rxfifo[], isr
assembled.append(0b100_00000_0001_0_000)
assembled.append(0b100_00000_0001_1_000)
if instruction[2] != "isr":
raise ValueError("mov rxfifo[] source must be isr")
assembled[-1] |= parse_rxfifo_brackets(instruction[1], "txput")
assembled[-1] ^= parse_rxfifo_brackets(instruction[1], "txput")
elif instruction[2].startswith("rxfifo["): # mov osr, rxfifo[]
assembled.append(0b100_00000_1001_0_000)
assembled.append(0b100_00000_1001_1_000)
if instruction[1] != "osr":
raise ValueError("mov ,rxfifo[] target must be osr")
assembled[-1] |= parse_rxfifo_brackets(instruction[2], "txget")
assembled[-1] ^= parse_rxfifo_brackets(instruction[2], "txget")
else:
assembled.append(0b101_00000_000_00_000)
assembled[-1] |= mov_destinations.index(instruction[1]) << 5
@ -388,30 +399,35 @@ class Program: # pylint: disable=too-few-public-methods
assembled.append(0b110_00000_0_0_0_00000)
irq_type = 0
if instruction[-1] == "prev":
idx = 1
if instruction[idx] == "wait":
assembled[-1] |= 0x20
idx += 1
elif instruction[idx] == "clear":
assembled[-1] |= 0x40
idx += 1
if instruction[idx] == "prev":
irq_type = 1
require_version(1, "irq prev")
instruction.pop()
elif instruction[-1] == "next":
idx += 1
elif instruction[idx] == "next":
irq_type = 3
require_version(1, "irq next")
instruction.pop()
elif instruction[-1] == "rel":
idx += 1
if instruction[-1] == "rel":
if irq_type != 0:
raise RuntimeError("cannot use next/prev with rel")
irq_type = 2
instruction.pop()
assembled[-1] |= irq_type << 3
num = int_in_range(instruction[-1], 0, 8, "irq index")
num = int_in_range(instruction[idx], 0, 8, "irq index")
assembled[-1] |= num
instruction.pop()
if len(instruction) > 1: # after rel has been removed
if instruction[-1] == "wait":
assembled[-1] |= 0x20
elif instruction[-1] == "clear":
assembled[-1] |= 0x40
# All other values are the default of set without waiting
elif instruction[0] == "set":
# instr delay dst data
assembled.append(0b111_00000_000_00000)

View file

@ -115,9 +115,10 @@ def test_dot_set() -> None:
def test_irq_v1() -> None:
assert_assembly_fails("irq 7 next")
assert_assembles_to(".pio_version 1\nirq 5 next", [0b110_00000_0_0_0_11_101])
assert_assembles_to(".pio_version 1\nirq wait 1 prev", [0b110_00000_0_0_1_01_001])
assert_assembly_fails("irq next 7")
assert_assembly_fails(".pio_version 1\nirq next 7 rel")
assert_assembles_to(".pio_version 1\nirq next 5", [0b110_00000_0_0_0_11_101])
assert_assembles_to(".pio_version 1\nirq wait prev 1", [0b110_00000_0_0_1_01_001])
def test_mov_v1() -> None:
@ -125,8 +126,8 @@ def test_mov_v1() -> None:
assert_assembly_fails(".pio_version 1\nmov osr, rxfifo[y]")
prefix = ".pio_version 1\n.fifo putget\n"
assert_assembly_fails(prefix + "mov osr, rxfifo[8]")
assert_assembles_to(prefix + "mov rxfifo[y], isr", [0b100_00000_0001_1_000])
assert_assembles_to(prefix + "mov osr, rxfifo[1]", [0b100_00000_1001_0_001])
assert_assembles_to(prefix + "mov rxfifo[y], isr", [0b100_00000_0001_0_000])
assert_assembles_to(prefix + "mov osr, rxfifo[1]", [0b100_00000_1001_1_001])
assert_assembly_fails("mov pindirs, null", errtype=ValueError)
assert_assembles_to(prefix + "mov pindirs, null", [0b101_00000_01100011])
@ -134,12 +135,12 @@ def test_mov_v1() -> None:
def test_wait_v1() -> None:
assert_assembly_fails("wait 0 jmppin")
assert_assembly_fails("wait 0 irq 5 next")
assert_assembly_fails("wait 0 irq next 5")
prefix = ".pio_version 1\n"
assert_assembly_fails(prefix + "wait 0 jmppin +")
assert_assembly_fails(prefix + "wait 0 jmppin + 7")
assert_assembles_to(prefix + "wait 0 jmppin + 3", [0b001_00000_0_11_00011])
assert_assembles_to(prefix + "wait 1 jmppin", [0b001_00000_1_11_00000])
assert_assembles_to(prefix + "wait 0 irq 5 next", [0b001_00000_0_10_11_101])
assert_assembles_to(prefix + "wait 1 irq 4 prev", [0b001_00000_1_10_01_100])
assert_assembles_to(prefix + "wait 0 irq next 5", [0b001_00000_0_10_11_101])
assert_assembles_to(prefix + "wait 1 irq prev 4", [0b001_00000_1_10_01_100])