def thumb_move_shifted_register(cpu: CPU, instr: int):
    """Execute a THUMB.1 instruction (move shifted register)"""
    rs = get_bits(instr, 3, 5)
    rd = get_bits(instr, 0, 2)
    opcode = get_bits(instr, 11, 12)
    offset = get_bits(instr, 6, 10)
    result, carry = cpu.compute_shift(cpu.regs.get(rs), opcode, offset, True)
    cpu.regs.set(rd, result)
    cpu.regs.cpsr.set_sign_flag(sign_32(result))
    cpu.regs.cpsr.set_zero_flag(result == 0)
    cpu.regs.cpsr.set_carry_flag(carry)
    cpu.advance_pc_thumb()
    cpu.next_fetch_access = MemoryAccess.SEQUENTIAL

def thumb_add_subtract(cpu: CPU, instr: int):
    """Execute a THUMB.2 instruction (add/subtract)"""
    rs = get_bits(instr, 3, 5)
    rd = get_bits(instr, 0, 2)
    opcode = get_bits(instr, 9, 10)
    immediate_bit = get_bit(instr, 10)
    op1 = cpu.regs.get(rs)
    op2 = get_bits(instr, 6, 8) if immediate_bit else cpu.regs.get(get_bits(instr, 6, 8))
    if opcode == 0:
        arm_alu_add(cpu, op1, op2, rd, True)
    elif opcode == 1:
        arm_alu_sub(cpu, op1, op2, rd, True)
    elif opcode == 2:
        arm_alu_add(cpu, op1, op2, rd, True)
    elif opcode == 3:
        arm_alu_sub(cpu, op1, op2, rd, True)
    cpu.advance_pc_thumb()
    cpu.next_fetch_access = MemoryAccess.SEQUENTIAL

def thumb_move_compare_add_subtract(cpu: CPU, instr: int):
    """Execute a THUMB.3 instruction (move/compare/add/subtract immediate)"""
    rd = get_bits(instr, 8, 10)
    opcode = get_bits(instr, 11, 12)
    value = get_bits(instr, 0, 7)
    if opcode == 0:
        arm_alu_mov(cpu, value, rd, True, cpu.regs.cpsr.get_carry_flag())
    elif opcode == 1:
        arm_alu_cmp(cpu, cpu.regs.get(rd), value)
    elif opcode == 2:
        arm_alu_add(cpu, cpu.regs.get(rd), value, rd, True)
    elif opcode == 3:
        arm_alu_sub(cpu, cpu.regs.get(rd), value, rd, True)
    cpu.advance_pc_thumb()
    cpu.next_fetch_access = MemoryAccess.SEQUENTIAL

def thumb_alu(cpu: CPU, instr: int):
    """Execute a THUMB.4 instruction (miscellaneous ALU operations)"""
    rs = get_bits(instr, 3, 5)
    rd = get_bits(instr, 0, 2)
    op1 = cpu.regs.get(rd)
    op2 = cpu.regs.get(rs)
    opcode = get_bits(instr, 6, 9)
    if opcode == ThumbALUOpcode.ThumbALUOpcode_AND:
        arm_alu_and(cpu, op1, op2, rd, True, cpu.regs.cpsr.get_carry_flag())
    elif opcode == ThumbALUOpcode.ThumbALUOpcode_EOR:
        arm_alu_eor(cpu, op1, op2, rd, True, cpu.regs.cpsr.get_carry_flag())
    elif opcode == ThumbALUOpcode.ThumbALUOpcode_LSL:
        thumb_alu_shift(cpu, op1, op2, rd, ShiftType.LSL)
    elif opcode == ThumbALUOpcode.ThumbALUOpcode_LSR:
        thumb_alu_shift(cpu, op1, op2, rd, ShiftType.LSR)
    elif opcode == ThumbALUOpcode.ThumbALUOpcode_ASR:
        thumb_alu_shift(cpu, op1, op2, rd, ShiftType.ASR)
    elif opcode == ThumbALUOpcode.ThumbALUOpcode_ADC:
        arm_alu_adc(cpu, op1, op2, rd, True)
    elif opcode == ThumbALUOpcode.ThumbALUOpcode_SBC:
        arm_alu_sbc(cpu, op1, op2, rd, True)
    elif opcode == ThumbALUOpcode.ThumbALUOpcode_ROR:
        thumb_alu_shift(cpu, op1, op2, rd, ShiftType.ROR)
    elif opcode == ThumbALUOpcode.ThumbALUOpcode_TST:
        arm_alu_tst(cpu, op1, op2, cpu.regs.cpsr.get_carry_flag())
    elif opcode == ThumbALUOpcode.NEG:
        arm_alu_sub(cpu, 0, op2, rd, True)
    elif opcode == ThumbALUOpcode.ThumbALUOpcode_CMP:
        arm_alu_cmp(cpu, op1, op2)
    elif opcode == ThumbALUOpcode.ThumbALUOpcode_CMN:
        arm_alu_cmn(cpu, op1, op2)
    elif opcode == ThumbALUOpcode.ThumbALUOpcode_ORR:
        arm_alu_orr(cpu, op1, op2, rd, True, cpu.regs.cpsr.get_carry_flag())
    elif opcode == ThumbALUOpcode.MUL:
        thumb_alu_multiply(cpu, op1, op2, rd)
    elif opcode == ThumbALUOpcode.ThumbALUOpcode_BIC:
        arm_alu_bic(cpu, op1, op2, rd, True, cpu.regs.cpsr.get_carry_flag())
    elif opcode == ThumbALUOpcode.ThumbALUOpcode_MVN:
        arm_alu_mvn(cpu, op2, rd, True, cpu.regs.cpsr.get_carry_flag())
    cpu.advance_pc_thumb()
    cpu.next_fetch_access = MemoryAccess.SEQUENTIAL

def thumb_alu_shift(cpu: CPU, value: int, shift: int, rd: int, shift_type: ShiftType):
    shift &= 255
    result, carry = cpu.compute_shift(value, shift_type, shift, False)
    cpu.regs.set(rd, result)
    cpu.regs.cpsr.set_sign_flag(sign_32(result))
    cpu.regs.cpsr.set_zero_flag(result == 0)
    cpu.regs.cpsr.set_carry_flag(carry)
    cpu.scheduler.idle(1)

def thumb_alu_multiply(cpu: CPU, op1: int, op2: int, rd: int):
    mask = 4294967295
    result = op1 * op2 & mask
    cpu.regs.set(rd, result)
    cpu.regs.cpsr.set_sign_flag(sign_32(result))
    cpu.regs.cpsr.set_zero_flag(result == 0)
    arm_multiply_idle(cpu, op1, True)

def thumb_high_reg_branch_exchange(cpu: CPU, instr: int):
    """Execute a THUMB.5 instruction (high register operations or branch exchange)"""
    rs = get_bit(instr, 6) << 3 | get_bits(instr, 3, 5)
    rd = get_bit(instr, 7) << 3 | get_bits(instr, 0, 2)
    opcode = get_bits(instr, 8, 9)
    if opcode == 0:
        cpu.regs.set(rd, add_32(cpu.regs.get(rd), cpu.regs.get(rs)))
        if rd == cpu.regs.PC:
            cpu.flush_pipeline()
            return
    elif opcode == 1:
        arm_alu_cmp(cpu, cpu.regs.get(rd), cpu.regs.get(rs))
    elif opcode == 2:
        cpu.regs.set(rd, cpu.regs.get(rs))
        if rd == cpu.regs.PC:
            cpu.flush_pipeline()
            return
    elif opcode == 3:
        address = cpu.regs.get(rs)
        cpu.regs.set_pc(address & ~1)
        cpu.regs.cpsr.set_state(get_bit(address, 0))
        cpu.flush_pipeline()
        return
    cpu.advance_pc_thumb()
    cpu.next_fetch_access = MemoryAccess.SEQUENTIAL

def thumb_get_address(cpu: CPU, instr: int):
    """Execute a THUMB.12 instruction (get address relative to SP/PC)"""
    opcode = get_bit(instr, 11)
    rd = get_bits(instr, 8, 10)
    offset = get_bits(instr, 0, 7) * 4
    if opcode:
        cpu.regs.set(rd, add_32(cpu.regs.get_sp(), offset))
    else:
        cpu.regs.set(rd, add_32(cpu.regs.get_pc() & ~2, offset))
    cpu.advance_pc_thumb()
    cpu.next_fetch_access = MemoryAccess.SEQUENTIAL

def thumb_add_offset_to_stack_pointer(cpu: CPU, instr: int):
    """Execute a THUMB.13 instruction (add offset to SP)"""
    sign = -1 if get_bit(instr, 7) else 1
    offset = sign * get_bits(instr, 0, 6) * 4
    cpu.regs.set_sp(add_32(cpu.regs.get_sp(), offset))
    cpu.advance_pc_thumb()
    cpu.next_fetch_access = MemoryAccess.SEQUENTIAL