def thumb_pc_relative_load(cpu: CPU, instr: int):
    """
    Execute a THUMB.6 instruction
    (load from memory with PC-relative offset)
    """
    rd = get_bits(instr, 8, 10)
    offset = get_bits(instr, 0, 7) << 2
    address = add_32(cpu.regs.get_pc() & ~2, offset)
    cpu.regs.set(rd, cpu.memory.read_32_ror(address, MemoryAccess.NON_SEQUENTIAL))
    cpu.scheduler.idle(1)
    cpu.advance_pc_thumb()
    cpu.next_fetch_access = MemoryAccess.NON_SEQUENTIAL

def thumb_load_store_register_offset(cpu: CPU, instr: int):
    """
    Execute a THUMB.7 instruction
    (load/store from/into memory with register offset)
    """
    ro = get_bits(instr, 6, 8)
    rb = get_bits(instr, 3, 5)
    rd = get_bits(instr, 0, 2)
    address = add_32(cpu.regs.get(rb), cpu.regs.get(ro))
    opcode = get_bits(instr, 10, 11)
    if opcode == 0:
        cpu.memory.write_32(address, cpu.regs.get(rd), MemoryAccess.NON_SEQUENTIAL)
    elif opcode == 1:
        cpu.memory.write_8(address, cpu.regs.get(rd), MemoryAccess.NON_SEQUENTIAL)
    elif opcode == 2:
        cpu.regs.set(rd, cpu.memory.read_32_ror(address, MemoryAccess.NON_SEQUENTIAL))
        cpu.scheduler.idle(1)
    elif opcode == 3:
        cpu.regs.set(rd, cpu.memory.read_8(address, MemoryAccess.NON_SEQUENTIAL))
        cpu.scheduler.idle(1)
    cpu.advance_pc_thumb()
    cpu.next_fetch_access = MemoryAccess.NON_SEQUENTIAL

def thumb_load_store_sign_extended(cpu: CPU, instr: int):
    """
    Execute a THUMB.8 instruction
    (load/store sign-extended byte/halfword from/into memory with register offset)
    """
    ro = get_bits(instr, 6, 8)
    rb = get_bits(instr, 3, 5)
    rd = get_bits(instr, 0, 2)
    address = add_32(cpu.regs.get(rb), cpu.regs.get(ro))
    opcode = get_bits(instr, 10, 11)
    if opcode == 0:
        cpu.memory.write_16(address, cpu.regs.get(rd), MemoryAccess.NON_SEQUENTIAL)
    elif opcode == 1:
        cpu.regs.set(rd, cpu.memory.read_8_signed(address, MemoryAccess.NON_SEQUENTIAL))
        cpu.scheduler.idle(1)
    elif opcode == 2:
        cpu.regs.set(rd, cpu.memory.read_16_ror(address, MemoryAccess.NON_SEQUENTIAL))
        cpu.scheduler.idle(1)
    elif opcode == 3:
        cpu.regs.set(rd, cpu.memory.read_16_signed(address, MemoryAccess.NON_SEQUENTIAL))
        cpu.scheduler.idle(1)
    cpu.advance_pc_thumb()
    cpu.next_fetch_access = MemoryAccess.NON_SEQUENTIAL

def thumb_load_store_immediate_offset(cpu: CPU, instr: int):
    """
    Execute a THUMB.9 instruction
    (load/store from/into memory with immediate offset)
    """
    rb = get_bits(instr, 3, 5)
    rd = get_bits(instr, 0, 2)
    opcode = get_bits(instr, 11, 12)
    offset = get_bits(instr, 6, 10) << 2 if opcode in (0, 1) else get_bits(instr, 6, 10)
    address = add_32(cpu.regs.get(rb), offset)
    if opcode == 0:
        cpu.memory.write_32(address, cpu.regs.get(rd), MemoryAccess.NON_SEQUENTIAL)
    elif opcode == 1:
        cpu.regs.set(rd, cpu.memory.read_32_ror(address, MemoryAccess.NON_SEQUENTIAL))
        cpu.scheduler.idle(1)
    elif opcode == 2:
        cpu.memory.write_8(address, cpu.regs.get(rd), MemoryAccess.NON_SEQUENTIAL)
    elif opcode == 3:
        cpu.regs.set(rd, cpu.memory.read_8(address, MemoryAccess.NON_SEQUENTIAL))
        cpu.scheduler.idle(1)
    cpu.advance_pc_thumb()
    cpu.next_fetch_access = MemoryAccess.NON_SEQUENTIAL

def thumb_load_store_halfword(cpu: CPU, instr: int):
    """
    Execute a THUMB.10 instruction
    (load/store halfword from/into memory with immediate offset)
    """
    rb = get_bits(instr, 3, 5)
    rd = get_bits(instr, 0, 2)
    offset = get_bits(instr, 6, 10) << 1
    address = add_32(cpu.regs.get(rb), offset)
    opcode = get_bit(instr, 11)
    if opcode:
        cpu.regs.set(rd, cpu.memory.read_16_ror(address, MemoryAccess.NON_SEQUENTIAL))
        cpu.scheduler.idle(1)
    else:
        cpu.memory.write_16(address, cpu.regs.get(rd), MemoryAccess.NON_SEQUENTIAL)
        cpu.scheduler.idle(1)
    cpu.advance_pc_thumb()
    cpu.next_fetch_access = MemoryAccess.NON_SEQUENTIAL

def thumb_sp_relative_load_store(cpu: CPU, instr: int):
    """
    Execute a THUMB.11 instruction
    (load/store from/into memory with SP-relative offset)
    """
    rd = get_bits(instr, 8, 10)
    offset = get_bits(instr, 0, 7) << 2
    address = add_32(cpu.regs.get_sp(), offset)
    opcode = get_bit(instr, 11)
    if opcode:
        cpu.regs.set(rd, cpu.memory.read_32_ror(address, MemoryAccess.NON_SEQUENTIAL))
        cpu.scheduler.idle(1)
    else:
        cpu.memory.write_32(address, cpu.regs.get(rd), MemoryAccess.NON_SEQUENTIAL)
    cpu.advance_pc_thumb()
    cpu.next_fetch_access = MemoryAccess.NON_SEQUENTIAL