import capstone

from ..platforms import Architecture, Byteorder
from .platformdef import PlatformDef, RegisterAliasDef, RegisterDef


class AArch64(PlatformDef):
    architecture = Architecture.AARCH64
    byteorder = Byteorder.LITTLE

    address_size = 8
    capstone_arch = capstone.CS_ARCH_ARM64
    capstone_mode = capstone.CS_MODE_ARM

    pc_register = "pc"
    sp_register = "sp"

    # NOTE: aarch64 has unconditional conditions.
    # "al" is always true, and "nv" is never true.
    conditional_branch_mnemonics = {
        # Conditional branches
        "b.eq",
        "b.ne",
        "b.cs",
        "b.cc",
        "b.mi",
        "b.pl",
        "b.vs",
        "b.vc",
        "b.hi",
        "b.ls",
        "b.ge",
        "b.lt",
        "b.gt",
        "b.le",
        # Consistent (unlikely?) conditional branches
        "bc.eq",
        "bc.ne",
        "bc.cs",
        "bc.cc",
        "bc.mi",
        "bc.pl",
        "bc.vs",
        "bc.vc",
        "bc.hi",
        "bc.ls",
        "bc.ge",
        "bc.lt",
        "bc.gt",
        "bc.le",
        # Compare and conditional branch
        # TODO: How to handle this?
        "cb.eq",
        "cb.ne",
        "cb.cs",
        "cb.cc",
        "cb.mi",
        "cb.pl",
        "cb.vs",
        "cb.vc",
        "cb.hi",
        "cb.ls",
        "cb.ge",
        "cb.lt",
        "cb.gt",
        "cb.le",
        # Extra mnemonics for cb opcodes
        "cbge",
        "cbhs",
        "cble",
        "cblo",
        "cbls",
        "cblt",
        "cbnz",
        "cbz",
        # Compare bytes and conditional branch
        "cbb.eq",
        "cbb.ne",
        "cbb.cs",
        "cbb.cc",
        "cbb.mi",
        "cbb.pl",
        "cbb.vs",
        "cbb.vc",
        "cbb.hi",
        "cbb.ls",
        "cbb.ge",
        "cbb.lt",
        "cbb.gt",
        "cbb.le",
        # Extra mnemonics for cbb opcodes
        "cbble",
        "cbblo",
        "cbbls",
        "cbblt",
        # Compare half-words and conditional branch
        "cbh.eq",
        "cbh.ne",
        "cbh.cs",
        "cbh.cc",
        "cbh.mi",
        "cbh.pl",
        "cbh.vs",
        "cbh.vc",
        "cbh.hi",
        "cbh.ls",
        "cbh.ge",
        "cbh.lt",
        "cbh.gt",
        "cbh.le",
        # Extra mnemonics for cbh opcodes
        "cbhle",
        "cbhlo",
        "cbhls",
        "cbhlt",
    }

    # TODO: Should arithmetic operations that impact flags be compares?
    compare_mnemonics = {
        # Integer comparison
        # AArch64 supports positive and negative variants of comparisons
        "cmn",
        "cmp",
        "tst",
        # Conditional comparison
        # This performs a comparison if the condition flags pass the desired test,
        # otherwise it sets the flags to an immediate.
        # NOTE: This takes a condition type, but it's encoded as an operand.
        "ccmn",
        "ccmp",
        # Compare with tag
        # Performs 56-bit comparison, likely to support tagged pointers
        "cmpp",
        # Vector comparisons
        "cmeq",
        "cmge",
        "cmgt",
        "cmhi",
        "cmhs",
        "cmle",
        "cmlt",
        "cmtst",
        # Floating-point comparisons
        "fcmeq",
        "fcmge",
        "fcmgt",
        "fcmle",
        "fcmlt",
        "fcmp",
        "fcmpe",
        # Floating-point conditional comparisons
        # NOTE: This takes a condition type, but it's encoded as an operand
        "fccmp",
        "fccmpe",
    }

    # Special registers:
    # x29: frame pointer
    # x30: link register
    # x31: stack pointer or zero, depending on instruction
    general_purpose_registers = [f"x{i}" for i in range(0, 29)]

    registers = {
        # *** General Purpose Registers ***
        "x0": RegisterDef(name="x0", size=8),
        "w0": RegisterAliasDef(name="w0", parent="x0", size=4, offset=0),
        "x1": RegisterDef(name="x1", size=8),
        "w1": RegisterAliasDef(name="w1", parent="x1", size=4, offset=0),
        "x2": RegisterDef(name="x2", size=8),
        "w2": RegisterAliasDef(name="w2", parent="x2", size=4, offset=0),
        "x3": RegisterDef(name="x3", size=8),
        "w3": RegisterAliasDef(name="w3", parent="x3", size=4, offset=0),
        "x4": RegisterDef(name="x4", size=8),
        "w4": RegisterAliasDef(name="w4", parent="x4", size=4, offset=0),
        "x5": RegisterDef(name="x5", size=8),
        "w5": RegisterAliasDef(name="w5", parent="x5", size=4, offset=0),
        "x6": RegisterDef(name="x6", size=8),
        "w6": RegisterAliasDef(name="w6", parent="x6", size=4, offset=0),
        "x7": RegisterDef(name="x7", size=8),
        "w7": RegisterAliasDef(name="w7", parent="x7", size=4, offset=0),
        "x8": RegisterDef(name="x8", size=8),
        "w8": RegisterAliasDef(name="w8", parent="x8", size=4, offset=0),
        "x9": RegisterDef(name="x9", size=8),
        "w9": RegisterAliasDef(name="w9", parent="x9", size=4, offset=0),
        "x10": RegisterDef(name="x10", size=8),
        "w10": RegisterAliasDef(name="w10", parent="x10", size=4, offset=0),
        "x11": RegisterDef(name="x11", size=8),
        "w11": RegisterAliasDef(name="w11", parent="x10", size=4, offset=0),
        "x12": RegisterDef(name="x12", size=8),
        "w12": RegisterAliasDef(name="w12", parent="x10", size=4, offset=0),
        "x13": RegisterDef(name="x13", size=8),
        "w13": RegisterAliasDef(name="w13", parent="x13", size=4, offset=0),
        "x14": RegisterDef(name="x14", size=8),
        "w14": RegisterAliasDef(name="w14", parent="x14", size=4, offset=0),
        "x15": RegisterDef(name="x15", size=8),
        "w15": RegisterAliasDef(name="w15", parent="x15", size=4, offset=0),
        "x16": RegisterDef(name="x16", size=8),
        "w16": RegisterAliasDef(name="w16", parent="x16", size=4, offset=0),
        "x17": RegisterDef(name="x17", size=8),
        "w17": RegisterAliasDef(name="w17", parent="x17", size=4, offset=0),
        "x18": RegisterDef(name="x18", size=8),
        "w18": RegisterAliasDef(name="w18", parent="x18", size=4, offset=0),
        "x19": RegisterDef(name="x19", size=8),
        "w19": RegisterAliasDef(name="w19", parent="x19", size=4, offset=0),
        "x20": RegisterDef(name="x20", size=8),
        "w20": RegisterAliasDef(name="w20", parent="x20", size=4, offset=0),
        "x21": RegisterDef(name="x21", size=8),
        "w21": RegisterAliasDef(name="w21", parent="x20", size=4, offset=0),
        "x22": RegisterDef(name="x22", size=8),
        "w22": RegisterAliasDef(name="w22", parent="x20", size=4, offset=0),
        "x23": RegisterDef(name="x23", size=8),
        "w23": RegisterAliasDef(name="w23", parent="x23", size=4, offset=0),
        "x24": RegisterDef(name="x24", size=8),
        "w24": RegisterAliasDef(name="w24", parent="x24", size=4, offset=0),
        "x25": RegisterDef(name="x25", size=8),
        "w25": RegisterAliasDef(name="w25", parent="x25", size=4, offset=0),
        "x26": RegisterDef(name="x26", size=8),
        "w26": RegisterAliasDef(name="w26", parent="x26", size=4, offset=0),
        "x27": RegisterDef(name="x27", size=8),
        "w27": RegisterAliasDef(name="w27", parent="x27", size=4, offset=0),
        "x28": RegisterDef(name="x28", size=8),
        "w28": RegisterAliasDef(name="w28", parent="x28", size=4, offset=0),
        "x29": RegisterDef(name="x29", size=8),
        "w29": RegisterAliasDef(name="w29", parent="x29", size=4, offset=0),
        "x30": RegisterDef(name="x30", size=8),
        "w30": RegisterAliasDef(name="w30", parent="x30", size=4, offset=0),
        # *** Program Counter ***
        "pc": RegisterDef(name="pc", size=8),
        # *** Stack Pointer ***
        "sp": RegisterDef(name="sp", size=8),
        "wsp": RegisterAliasDef(name="wsp", parent="sp", size=4, offset=0),
        # *** Frame Pointer ***
        "fp": RegisterAliasDef(name="fp", parent="x29", size=8, offset=0),
        # *** Link Register ***
        "lr": RegisterAliasDef(name="lr", parent="x30", size=8, offset=0),
        # *** Zero Register ***
        "xzr": RegisterDef(name="xzr", size=8),
        "wzr": RegisterAliasDef(name="wzr", parent="xzr", size=4, offset=0),
        # *** System Control Registers ***
        # NOTE: "_elX" indicates that only exception level X or greater can access this register.
        # NOTE: This list is far from complete; it only covers what Unicorn supports
        # Condition Code Register
        "fpcr": RegisterDef(name="fpcr", size=8),
        # Floating Point Status Register
        "fpsr": RegisterDef(name="fpsr", size=8),
        # Banked stack pointers for exception handlers
        "sp_el0": RegisterDef(name="sp_el0", size=8),
        "sp_el1": RegisterDef(name="sp_el1", size=8),
        "sp_el2": RegisterDef(name="sp_el2", size=8),
        "sp_el3": RegisterDef(name="sp_el3", size=8),
        # Banked link registers for exception handlers
        # NOTE: Unicorn thinks there's an elr_el0; according to docs, it doesn't exist
        "elr_el1": RegisterDef(name="elr_el1", size=8),
        "elr_el2": RegisterDef(name="elr_el2", size=8),
        "elr_el3": RegisterDef(name="elr_el3", size=8),
        # Banked exception syndrome registers for exception handlers
        # NOTE: Unicorn thinks there's a far_el0; according to docs, it doesn't exist
        "far_el1": RegisterDef(name="far_el1", size=8),
        "far_el2": RegisterDef(name="far_el2", size=8),
        "far_el3": RegisterDef(name="far_el3", size=8),
        # Banked vector base address registers for exception handlers
        # NOTE: vbar_el0 and vbar_el1 are aliases for each other.
        # Since vbar_el0 doesn't exist in angr, vbar_el1 has to be the "real" copy.
        "vbar_el1": RegisterDef(name="vbar_el1", size=8),
        "vbar_el0": RegisterAliasDef(
            name="vbar_el0", parent="vbar_el1", size=8, offset=0
        ),
        "vbar_el2": RegisterDef(name="vbar_el2", size=8),
        "vbar_el3": RegisterDef(name="vbar_el3", size=8),
        # Coprocessor access control register
        "cpacr_el1": RegisterDef(name="cpacr_el1", size=8),
        # Memory Attribute Indirection Register
        "mair_el1": RegisterDef(name="mair_el1", size=8),
        # Physical Address Register
        "par_el1": RegisterDef(name="par_el1", size=8),
        # Translation Table Zero Base Register
        "ttbr0_el1": RegisterDef(name="ttbr0_el1", size=8),
        # Translation Table One Base Register
        "ttbr1_el1": RegisterDef(name="ttbr1_el1", size=8),
        # Thread ID Register
        # NOTE: According to docs, there should be an el2 and el3 copy, too.
        "tpidr_el0": RegisterDef(name="tpidr_el0", size=8),
        "tpidr_el1": RegisterDef(name="tpidr_el1", size=8),
        # Userspace-visible Thread ID register
        "tpidrro_el0": RegisterDef(name="tpidrro_el0", size=8),
        # *** Floating Point Registers ***
        # Scalar Floating Point Registers
        "q0": RegisterDef(name="q0", size=16),
        "d0": RegisterAliasDef(name="d0", parent="q0", size=8, offset=0),
        "s0": RegisterAliasDef(name="s0", parent="q0", size=4, offset=0),
        "h0": RegisterAliasDef(name="h0", parent="q0", size=2, offset=0),
        "b0": RegisterAliasDef(name="b0", parent="q0", size=1, offset=0),
        "q1": RegisterDef(name="q1", size=16),
        "d1": RegisterAliasDef(name="d1", parent="q1", size=8, offset=0),
        "s1": RegisterAliasDef(name="s1", parent="q1", size=4, offset=0),
        "h1": RegisterAliasDef(name="h1", parent="q1", size=2, offset=0),
        "b1": RegisterAliasDef(name="b1", parent="q1", size=1, offset=0),
        "q2": RegisterDef(name="q2", size=16),
        "d2": RegisterAliasDef(name="d2", parent="q2", size=8, offset=0),
        "s2": RegisterAliasDef(name="s2", parent="q2", size=4, offset=0),
        "h2": RegisterAliasDef(name="h2", parent="q2", size=2, offset=0),
        "b2": RegisterAliasDef(name="b2", parent="q2", size=1, offset=0),
        "q3": RegisterDef(name="q3", size=16),
        "d3": RegisterAliasDef(name="d3", parent="q3", size=8, offset=0),
        "s3": RegisterAliasDef(name="s3", parent="q3", size=4, offset=0),
        "h3": RegisterAliasDef(name="h3", parent="q3", size=2, offset=0),
        "b3": RegisterAliasDef(name="b3", parent="q3", size=1, offset=0),
        "q4": RegisterDef(name="q4", size=16),
        "d4": RegisterAliasDef(name="d4", parent="q4", size=8, offset=0),
        "s4": RegisterAliasDef(name="s4", parent="q4", size=4, offset=0),
        "h4": RegisterAliasDef(name="h4", parent="q4", size=2, offset=0),
        "b4": RegisterAliasDef(name="b4", parent="q4", size=1, offset=0),
        "q5": RegisterDef(name="q5", size=16),
        "d5": RegisterAliasDef(name="d5", parent="q5", size=8, offset=0),
        "s5": RegisterAliasDef(name="s5", parent="q5", size=4, offset=0),
        "h5": RegisterAliasDef(name="h5", parent="q5", size=2, offset=0),
        "b5": RegisterAliasDef(name="b5", parent="q5", size=1, offset=0),
        "q6": RegisterDef(name="q6", size=16),
        "d6": RegisterAliasDef(name="d6", parent="q6", size=8, offset=0),
        "s6": RegisterAliasDef(name="s6", parent="q6", size=4, offset=0),
        "h6": RegisterAliasDef(name="h6", parent="q6", size=2, offset=0),
        "b6": RegisterAliasDef(name="b6", parent="q6", size=1, offset=0),
        "q7": RegisterDef(name="q7", size=16),
        "d7": RegisterAliasDef(name="d7", parent="q7", size=8, offset=0),
        "s7": RegisterAliasDef(name="s7", parent="q7", size=4, offset=0),
        "h7": RegisterAliasDef(name="h7", parent="q7", size=2, offset=0),
        "b7": RegisterAliasDef(name="b7", parent="q7", size=1, offset=0),
        "q8": RegisterDef(name="q8", size=16),
        "d8": RegisterAliasDef(name="d8", parent="q8", size=8, offset=0),
        "s8": RegisterAliasDef(name="s8", parent="q8", size=4, offset=0),
        "h8": RegisterAliasDef(name="h8", parent="q8", size=2, offset=0),
        "b8": RegisterAliasDef(name="b8", parent="q8", size=1, offset=0),
        "q9": RegisterDef(name="q9", size=16),
        "d9": RegisterAliasDef(name="d9", parent="q9", size=8, offset=0),
        "s9": RegisterAliasDef(name="s9", parent="q9", size=4, offset=0),
        "h9": RegisterAliasDef(name="h9", parent="q9", size=2, offset=0),
        "b9": RegisterAliasDef(name="b9", parent="q9", size=1, offset=0),
        "q10": RegisterDef(name="q10", size=16),
        "d10": RegisterAliasDef(name="d10", parent="q10", size=8, offset=0),
        "s10": RegisterAliasDef(name="s10", parent="q10", size=4, offset=0),
        "h10": RegisterAliasDef(name="h10", parent="q10", size=2, offset=0),
        "b10": RegisterAliasDef(name="b10", parent="q10", size=1, offset=0),
        "q11": RegisterDef(name="q11", size=16),
        "d11": RegisterAliasDef(name="d11", parent="q11", size=8, offset=0),
        "s11": RegisterAliasDef(name="s11", parent="q11", size=4, offset=0),
        "h11": RegisterAliasDef(name="h11", parent="q11", size=2, offset=0),
        "b11": RegisterAliasDef(name="b11", parent="q11", size=1, offset=0),
        "q12": RegisterDef(name="q12", size=16),
        "d12": RegisterAliasDef(name="d12", parent="q12", size=8, offset=0),
        "s12": RegisterAliasDef(name="s12", parent="q12", size=4, offset=0),
        "h12": RegisterAliasDef(name="h12", parent="q12", size=2, offset=0),
        "b12": RegisterAliasDef(name="b12", parent="q12", size=1, offset=0),
        "q13": RegisterDef(name="q13", size=16),
        "d13": RegisterAliasDef(name="d13", parent="q13", size=8, offset=0),
        "s13": RegisterAliasDef(name="s13", parent="q13", size=4, offset=0),
        "h13": RegisterAliasDef(name="h13", parent="q13", size=2, offset=0),
        "b13": RegisterAliasDef(name="b13", parent="q13", size=1, offset=0),
        "q14": RegisterDef(name="q14", size=16),
        "d14": RegisterAliasDef(name="d14", parent="q14", size=8, offset=0),
        "s14": RegisterAliasDef(name="s14", parent="q14", size=4, offset=0),
        "h14": RegisterAliasDef(name="h14", parent="q14", size=2, offset=0),
        "b14": RegisterAliasDef(name="b14", parent="q14", size=1, offset=0),
        "q15": RegisterDef(name="q15", size=16),
        "d15": RegisterAliasDef(name="d15", parent="q15", size=8, offset=0),
        "s15": RegisterAliasDef(name="s15", parent="q15", size=4, offset=0),
        "h15": RegisterAliasDef(name="h15", parent="q15", size=2, offset=0),
        "b15": RegisterAliasDef(name="b15", parent="q15", size=1, offset=0),
        "q16": RegisterDef(name="q16", size=16),
        "d16": RegisterAliasDef(name="d16", parent="q16", size=8, offset=0),
        "s16": RegisterAliasDef(name="s16", parent="q16", size=4, offset=0),
        "h16": RegisterAliasDef(name="h16", parent="q16", size=2, offset=0),
        "b16": RegisterAliasDef(name="b16", parent="q16", size=1, offset=0),
        "q17": RegisterDef(name="q17", size=16),
        "d17": RegisterAliasDef(name="d17", parent="q17", size=8, offset=0),
        "s17": RegisterAliasDef(name="s17", parent="q17", size=4, offset=0),
        "h17": RegisterAliasDef(name="h17", parent="q17", size=2, offset=0),
        "b17": RegisterAliasDef(name="b17", parent="q17", size=1, offset=0),
        "q18": RegisterDef(name="q18", size=16),
        "d18": RegisterAliasDef(name="d18", parent="q18", size=8, offset=0),
        "s18": RegisterAliasDef(name="s18", parent="q18", size=4, offset=0),
        "h18": RegisterAliasDef(name="h18", parent="q18", size=2, offset=0),
        "b18": RegisterAliasDef(name="b18", parent="q18", size=1, offset=0),
        "q19": RegisterDef(name="q19", size=16),
        "d19": RegisterAliasDef(name="d19", parent="q19", size=8, offset=0),
        "s19": RegisterAliasDef(name="s19", parent="q19", size=4, offset=0),
        "h19": RegisterAliasDef(name="h19", parent="q19", size=2, offset=0),
        "b19": RegisterAliasDef(name="b19", parent="q19", size=1, offset=0),
        "q20": RegisterDef(name="q20", size=16),
        "d20": RegisterAliasDef(name="d20", parent="q20", size=8, offset=0),
        "s20": RegisterAliasDef(name="s20", parent="q20", size=4, offset=0),
        "h20": RegisterAliasDef(name="h20", parent="q20", size=2, offset=0),
        "b20": RegisterAliasDef(name="b20", parent="q20", size=1, offset=0),
        "q21": RegisterDef(name="q21", size=16),
        "d21": RegisterAliasDef(name="d21", parent="q21", size=8, offset=0),
        "s21": RegisterAliasDef(name="s21", parent="q21", size=4, offset=0),
        "h21": RegisterAliasDef(name="h21", parent="q21", size=2, offset=0),
        "b21": RegisterAliasDef(name="b21", parent="q21", size=1, offset=0),
        "q22": RegisterDef(name="q22", size=16),
        "d22": RegisterAliasDef(name="d22", parent="q22", size=8, offset=0),
        "s22": RegisterAliasDef(name="s22", parent="q22", size=4, offset=0),
        "h22": RegisterAliasDef(name="h22", parent="q22", size=2, offset=0),
        "b22": RegisterAliasDef(name="b22", parent="q22", size=1, offset=0),
        "q23": RegisterDef(name="q23", size=16),
        "d23": RegisterAliasDef(name="d23", parent="q23", size=8, offset=0),
        "s23": RegisterAliasDef(name="s23", parent="q23", size=4, offset=0),
        "h23": RegisterAliasDef(name="h23", parent="q23", size=2, offset=0),
        "b23": RegisterAliasDef(name="b23", parent="q23", size=1, offset=0),
        "q24": RegisterDef(name="q24", size=16),
        "d24": RegisterAliasDef(name="d24", parent="q24", size=8, offset=0),
        "s24": RegisterAliasDef(name="s24", parent="q24", size=4, offset=0),
        "h24": RegisterAliasDef(name="h24", parent="q24", size=2, offset=0),
        "b24": RegisterAliasDef(name="b24", parent="q24", size=1, offset=0),
        "q25": RegisterDef(name="q25", size=16),
        "d25": RegisterAliasDef(name="d25", parent="q25", size=8, offset=0),
        "s25": RegisterAliasDef(name="s25", parent="q25", size=4, offset=0),
        "h25": RegisterAliasDef(name="h25", parent="q25", size=2, offset=0),
        "b25": RegisterAliasDef(name="b25", parent="q25", size=1, offset=0),
        "q26": RegisterDef(name="q26", size=16),
        "d26": RegisterAliasDef(name="d26", parent="q26", size=8, offset=0),
        "s26": RegisterAliasDef(name="s26", parent="q26", size=4, offset=0),
        "h26": RegisterAliasDef(name="h26", parent="q26", size=2, offset=0),
        "b26": RegisterAliasDef(name="b26", parent="q26", size=1, offset=0),
        "q27": RegisterDef(name="q27", size=16),
        "d27": RegisterAliasDef(name="d27", parent="q27", size=8, offset=0),
        "s27": RegisterAliasDef(name="s27", parent="q27", size=4, offset=0),
        "h27": RegisterAliasDef(name="h27", parent="q27", size=2, offset=0),
        "b27": RegisterAliasDef(name="b27", parent="q27", size=1, offset=0),
        "q28": RegisterDef(name="q28", size=16),
        "d28": RegisterAliasDef(name="d28", parent="q28", size=8, offset=0),
        "s28": RegisterAliasDef(name="s28", parent="q28", size=4, offset=0),
        "h28": RegisterAliasDef(name="h28", parent="q28", size=2, offset=0),
        "b28": RegisterAliasDef(name="b28", parent="q28", size=1, offset=0),
        "q29": RegisterDef(name="q29", size=16),
        "d29": RegisterAliasDef(name="d29", parent="q29", size=8, offset=0),
        "s29": RegisterAliasDef(name="s29", parent="q29", size=4, offset=0),
        "h29": RegisterAliasDef(name="h29", parent="q29", size=2, offset=0),
        "b29": RegisterAliasDef(name="b29", parent="q29", size=1, offset=0),
        "q30": RegisterDef(name="q30", size=16),
        "d30": RegisterAliasDef(name="d30", parent="q30", size=8, offset=0),
        "s30": RegisterAliasDef(name="s30", parent="q30", size=4, offset=0),
        "h30": RegisterAliasDef(name="h30", parent="q30", size=2, offset=0),
        "b30": RegisterAliasDef(name="b30", parent="q30", size=1, offset=0),
        "q31": RegisterDef(name="q31", size=16),
        "d31": RegisterAliasDef(name="d31", parent="q31", size=8, offset=0),
        "s31": RegisterAliasDef(name="s31", parent="q31", size=4, offset=0),
        "h31": RegisterAliasDef(name="h31", parent="q31", size=2, offset=0),
        "b31": RegisterAliasDef(name="b31", parent="q31", size=1, offset=0),
        # Vector registers
        # TODO: Figure out how to model these
    }
