"""Cortex-M startup data model, not an instruction-set emulator."""
import struct


def initialize(ram, image, data_start, bss_start, bss_end):
    if not 0 <= data_start <= data_start + len(image) <= bss_start <= bss_end <= len(ram):
        raise ValueError("invalid memory layout")
    ram[data_start:data_start + len(image)] = image
    ram[bss_start:bss_end] = b"\x00" * (bss_end - bss_start)


def main():
    ram = bytearray([0xA5] * 64)
    initial = struct.pack("<II", 42, 0x12345678)
    initialize(ram, initial, data_start=8, bss_start=16, bss_end=32)
    assert struct.unpack("<II", ram[8:16]) == (42, 0x12345678)
    assert ram[16:32] == bytearray(16)
    assert ram[:8] == bytes([0xA5] * 8)
    assert ram[32:] == bytes([0xA5] * 32)
    vectors = struct.pack("<II", 0x20010000, 0x08000101)
    stack, entry = struct.unpack("<II", vectors)
    assert stack % 8 == 0
    assert entry & 1 == 1
    assert entry & ~1 == 0x08000100
    try:
        initialize(ram, initial, 8, 16, 65)
    except ValueError:
        pass
    else:
        raise AssertionError("out-of-bounds layout was accepted")
    print("data=[42, 0x12345678], bss=zero, guard bytes=unchanged")
    print("PASS")


if __name__ == "__main__":
    main()
