def encode_ctrl_instr(instr):
    """
    Encode a branch or jump instruction as a number.
    :param instr: list, instruction operands, e.g. ['beq', 'r1', 'r2', '10']
    :return: int, encoded instruction.
    """
    hex_instr = 0

    # BEQ and JMP have different encodings. Consider both cases.
    if instr[0] == 'beq':
        # Encode opcode.
        hex_instr += 0x30 << 25

        # Encode first source register.
        src_1_reg = int(''.join(c for c in instr[1] if c.isdigit()), 16)
        hex_instr += src_1_reg << 15

        # Encode second source register.
        src_2_reg = int(''.join(c for c in instr[2] if c.isdigit()), 16)
        hex_instr += src_2_reg << 10

        # Encode offset.
        off_val = int(instr[3], 16)
        off_low = off_val & 0x03ff
        off_hi = off_val & 0x7c00
        hex_instr += off_hi << 20
        hex_instr += off_low

    else:
        # Encode opcode.
        hex_instr += 0x31 << 25

        # Encode source register.
        src_reg = int(''.join(c for c in instr[1] if c.isdigit()), 16)
        hex_instr += src_reg << 15

        # Encode offset.
        off_val = int(instr[2], 16)
        off_low = off_val & 0x003ff
        off_med = off_val & 0x07c00
        off_hi = off_val & 0xf8000
        hex_instr += off_hi << 20
        hex_instr += off_med << 10
        hex_instr += off_low
    return hex_instr