import time, array
from random import randint
time.sleep(0.1) # Wait for USB to become ready
from sys import exit

print("Hello, Pi Pico!")
@micropython.asm_thumb
def bubble_sort(r0, r1):  # r0 = address of array, r1 = number of elements
    label(loop_start)
    mov(r3, r1)            # r3 will track the number of elements to end of array
    sub(r3, r3, 1)         # decrement r3 for zero indexing
    mov(r4, r0)            # r4 will be the pointer to the current element in array

    label(inner_loop_start)
    ldrb(r5, [r4, 0])      # Load current element
    ldrb(r6, [r4, 1])      # Load next element

    cmp(r5, r6)
    bge(no_swap)
    strb(r6, [r4, 0])      # Swap the elements
    strb(r5, [r4, 1])

    label(no_swap)
    add(r4, r4, 1)         # Move to the next element
    sub(r3, r3, 1)         # Decrement the loop counter
    cmp(r3, 0)             # Compare counter with 0
    bgt(inner_loop_start)  # If counter > 0, loop again

    sub(r1, r1, 1)         # Decrement number of elements to sort
    cmp(r1, 1)             # If we've sorted enough elements, we can stop
    bgt(loop_start)        # Otherwise, start the outer loop again

@micropython.asm_thumb
def bubble_sort_optimized(r0, r1):  # r0 = address of array, r1 = number of elements
    mov(r2, r1)            # r2 keeps the original count for resetting the swap flag position
    label(outer_loop_start)
    mov(r3, r1)            # r3 is the inner loop counter
    sub(r3, r3, 1)         # decrement for zero indexing
    mov(r4, r0)            # r4 is the pointer to the current element

    # Initialize swap flag to 0 (no swaps)
    # Swap flag will be at address r0 + r1 (outside the array data)
    add(r7, r0, r2)        # r7 points to the swap flag
    mov(r5, 0)
    strb(r5, [r7, 0])      # Set swap flag to 0

    label(inner_loop_start)
    ldrb(r5, [r4, 0])      # Load current element
    ldrb(r6, [r4, 1])      # Load next element

    cmp(r5, r6)
    bge(no_swap)
    strb(r6, [r4, 0])      # Swap the elements
    strb(r5, [r4, 1])
    mov(r5, 1)
    strb(r5, [r7, 0])      # Set swap flag to 1

    label(no_swap)
    add(r4, r4, 1)         # Move to the next element
    sub(r3, r3, 1)         # Decrement the loop counter
    cmp(r3, 0)             # Check if the loop should continue
    bgt(inner_loop_start)

    ldrb(r5, [r7, 0])      # Check the swap flag
    cmp(r5, 0)
    beq(early_exit)        # If no swaps, exit early

    sub(r1, r1, 1)         # Decrement the total number of elements to sort
    cmp(r1, 1)
    bgt(outer_loop_start)  # Continue the outer loop if more elements to sort

    label(early_exit)

@micropython.asm_thumb #pseudo random
def prng_lfsr(r0):  # r0 = seed (32-bit)
    mov(r1, r0)            # Copy seed to r1

    # Perform one LFSR iteration to get the next state
    lsr(r2, r1, 31)        # Isolate the highest bit (bit 31), shift it into the lowest bit position
    eor(r1, r2)            # XOR the isolated bit with the current state

    lsr(r2, r1, 21)        # Isolate bit 21, shift it into the lowest bit position
    mov(r3, 1)             # Prepare mask for bit isolation
    and_(r2, r3)           # Mask all but the least significant bit
    eor(r1, r2)            # XOR bit 21 into the feedback

    lsr(r2, r1, 1)         # Isolate bit 1, shift it into the lowest bit position
    and_(r2, r3)           # Mask all but the least significant bit using the same mask r3
    eor(r1, r2)            # XOR bit 1 into the feedback

    and_(r2, r1)           # Directly isolate the lowest bit of r1 (no shift needed)
    eor(r1, r2)            # XOR bit 0 into the feedback

    lsr(r1, r1, 1)         # Shift the register right by 1
    lsl(r2, r2, 31)        # Move the last XOR result back to the highest bit position
    orr(r1, r2)            # Insert the feedback result into the highest bit of r1

    mov(r0, r1)            # Move the result back to r0 for the output

@micropython.asm_thumb
def swap_registers(r0, r1):
    # r0 = r0 XOR r1
    eor(r0, r1)
    
    # r1 = r1 XOR r0 (which is now r0 XOR r1)
    eor(r1, r0)
    
    # r0 = r0 XOR r1 (which is now the original r1)
    eor(r0, r1)

print(swap_registers(1,2))
exit()

seed = 9998
seed = prng_lfsr(seed)
print(seed)

exit()

ARY = array.array('B',(randint(0,255) for i in range(10)))
print(ARY)
#bubble_sort(ARY,10)
bubble_sort_optimized(ARY,10)
print(ARY)
BOOTSELLED1239USBRaspberryPiPico©2020RP2-8020/21P64M15.00TTT