# -*- coding: utf-8 -*-

# This code is part of Amoco
# Copyright (C) 2006-2011 Axel Tillequin (bdcht3@gmail.com)
# published under GPLv2 license

# spec_xxx files are providers for instruction objects.

from amoco.arch.core import ispec, InstructionError
from amoco.arch.core import (
    type_data_processing,
    type_control_flow,
    type_cpu_state,
    type_system,
)
from . import env
from .utils import ARMExpandImm, DecodeShift


# ------------------------------------------------------
# amoco ARMv7++ instruction specs:
# ------------------------------------------------------

ISPECS = []


# ruff: noqa: F811


@ispec("32[ .cond(4) 00 1 0000 S Rn(4) Rd(4) imm12(12) ]", mnemonic="AND")
@ispec("32[ .cond(4) 00 1 0001 S Rn(4) Rd(4) imm12(12) ]", mnemonic="EOR")
@ispec("32[ .cond(4) 00 1 0010 S Rn(4) Rd(4) imm12(12) ]", mnemonic="SUB")
@ispec("32[ .cond(4) 00 1 0011 S Rn(4) Rd(4) imm12(12) ]", mnemonic="RSB")
@ispec("32[ .cond(4) 00 1 0100 S Rn(4) Rd(4) imm12(12) ]", mnemonic="ADD")
@ispec("32[ .cond(4) 00 1 0101 S Rn(4) Rd(4) imm12(12) ]", mnemonic="ADC")
@ispec("32[ .cond(4) 00 1 0110 S Rn(4) Rd(4) imm12(12) ]", mnemonic="SBC")
@ispec("32[ .cond(4) 00 1 0111 S Rn(4) Rd(4) imm12(12) ]", mnemonic="RSC")
@ispec("32[ .cond(4) 00 1 1100 S Rn(4) Rd(4) imm12(12) ]", mnemonic="ORR")
@ispec("32[ .cond(4) 00 1 1110 S Rn(4) Rd(4) imm12(12) ]", mnemonic="BIC")
def A_default(obj, S, Rn, Rd, imm12):
    obj.setflags = S == 1
    obj.n = env.regs[Rn]
    obj.d = env.regs[Rd]
    obj.imm32 = ARMExpandImm(imm12)
    obj.operands = [obj.d, obj.n, obj.imm32]
    obj.type = type_data_processing
    if obj.d == env.pc:
        obj.type = type_control_flow


@ispec(
    "32[ .cond(4) 00 0 0000 S Rn(4) Rd(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="AND"
)
@ispec(
    "32[ .cond(4) 00 0 0001 S Rn(4) Rd(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="EOR"
)
@ispec(
    "32[ .cond(4) 00 0 0010 S Rn(4) Rd(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="SUB"
)
@ispec(
    "32[ .cond(4) 00 0 0011 S Rn(4) Rd(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="RSB"
)
@ispec(
    "32[ .cond(4) 00 0 0100 S Rn(4) Rd(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="ADD"
)
@ispec(
    "32[ .cond(4) 00 0 0101 S Rn(4) Rd(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="ADC"
)
@ispec(
    "32[ .cond(4) 00 0 0110 S Rn(4) Rd(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="SBC"
)
@ispec(
    "32[ .cond(4) 00 0 0111 S Rn(4) Rd(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="RSC"
)
@ispec(
    "32[ .cond(4) 00 0 1100 S Rn(4) Rd(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="ORR"
)
@ispec(
    "32[ .cond(4) 00 0 1110 S Rn(4) Rd(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="BIC"
)
def A_sreg(obj, S, Rn, Rd, imm5, stype, Rm):
    obj.setflags = S == 1
    obj.n = env.regs[Rn]
    obj.d = env.regs[Rd]
    obj.m = DecodeShift(stype, env.regs[Rm], env.cst(imm5, 5))
    obj.operands = [obj.d, obj.n, obj.m]
    obj.type = type_data_processing
    if obj.d == env.pc:
        obj.type = type_control_flow


@ispec(
    "32[ .cond(4) 00 0 0000 S Rn(4) Rd(4) Rs(4) 0 stype(2) 1 Rm(4) ]", mnemonic="AND"
)
@ispec(
    "32[ .cond(4) 00 0 0001 S Rn(4) Rd(4) Rs(4) 0 stype(2) 1 Rm(4) ]", mnemonic="EOR"
)
@ispec(
    "32[ .cond(4) 00 0 0010 S Rn(4) Rd(4) Rs(4) 0 stype(2) 1 Rm(4) ]", mnemonic="SUB"
)
@ispec(
    "32[ .cond(4) 00 0 0011 S Rn(4) Rd(4) Rs(4) 0 stype(2) 1 Rm(4) ]", mnemonic="RSB"
)
@ispec(
    "32[ .cond(4) 00 0 0100 S Rn(4) Rd(4) Rs(4) 0 stype(2) 1 Rm(4) ]", mnemonic="ADD"
)
@ispec(
    "32[ .cond(4) 00 0 0101 S Rn(4) Rd(4) Rs(4) 0 stype(2) 1 Rm(4) ]", mnemonic="ADC"
)
@ispec(
    "32[ .cond(4) 00 0 0110 S Rn(4) Rd(4) Rs(4) 0 stype(2) 1 Rm(4) ]", mnemonic="SBC"
)
@ispec(
    "32[ .cond(4) 00 0 0111 S Rn(4) Rd(4) Rs(4) 0 stype(2) 1 Rm(4) ]", mnemonic="RSC"
)
@ispec(
    "32[ .cond(4) 00 0 1100 S Rn(4) Rd(4) Rs(4) 0 stype(2) 1 Rm(4) ]", mnemonic="ORR"
)
@ispec(
    "32[ .cond(4) 00 0 1110 S Rn(4) Rd(4) Rs(4) 0 stype(2) 1 Rm(4) ]", mnemonic="BIC"
)
def A_sreg(obj, S, Rn, Rd, Rs, stype, Rm):
    obj.setflags = S == 1
    obj.n = env.regs[Rn]
    if 15 in (Rd, Rs, Rm, Rn):
        raise InstructionError(obj)
    obj.d = env.regs[Rd]
    obj.m = DecodeShift(stype, env.regs[Rm], env.regs[Rs])
    obj.operands = [obj.d, obj.n, obj.m]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 00 1 0100 S 1111 Rd(4) imm12(12) ]", mnemonic="ADR", add=True)
@ispec("32[ .cond(4) 00 1 0010 S 1111 Rd(4) imm12(12) ]", mnemonic="ADR", add=False)
def A_adr(obj, S, Rd, imm12):
    obj.setflags = S == 1
    obj.d = env.regs[Rd]
    obj.imm32 = ARMExpandImm(imm12)
    obj.operands = [obj.d, obj.imm32]
    obj.type = type_data_processing
    if obj.d == env.pc:
        obj.type = type_control_flow


@ispec("32[ .cond(4) 00 1 1101 S 0000 Rd(4) imm12(12) ]", mnemonic="MOV")
@ispec("32[ .cond(4) 00 1 1111 S 0000 Rd(4) imm12(12) ]", mnemonic="MVN")
def A_default(obj, S, Rd, imm12):
    obj.setflags = S == 1
    obj.d = env.regs[Rd]
    obj.imm32 = ARMExpandImm(imm12)
    obj.operands = [obj.d, obj.imm32]
    obj.type = type_data_processing
    if obj.d == env.pc:
        obj.type = type_control_flow


@ispec("32[ .cond(4) 00 0 1101 S 0000 Rd(4) imm5(5) 100 Rm(4) ]", mnemonic="ASR")
@ispec("32[ .cond(4) 00 0 1101 S 0000 Rd(4) imm5(5) 000 Rm(4) ]", mnemonic="LSL")
@ispec("32[ .cond(4) 00 0 1101 S 0000 Rd(4) imm5(5) 010 Rm(4) ]", mnemonic="LSR")
@ispec("32[ .cond(4) 00 0 1101 S 0000 Rd(4) imm5(5) 110 Rm(4) ]", mnemonic="ROR")
def A_default(obj, S, Rd, imm5, Rm):
    obj.setflags = S == 1
    obj.d = env.regs[Rd]
    obj.m = env.regs[Rm]
    obj.type = type_data_processing
    if obj.d == env.pc:
        obj.type = type_control_flow
    if imm5 == 0:
        shift_n = 32 if obj.mnemonic in ("LSR", "ASR") else imm5
        if obj.mnemonic == "ROR":
            raise InstructionError(obj)  # see RRX
    else:
        shift_n = imm5
    obj.operands = [obj.d, obj.m, env.cst(shift_n, 5)]


@ispec("32[ .cond(4) 00 0 1101 S 0000 Rd(4) Rm(4) 0101 Rn(4) ]", mnemonic="ASR")
@ispec("32[ .cond(4) 00 0 1101 S 0000 Rd(4) Rm(4) 0001 Rn(4) ]", mnemonic="LSL")
@ispec("32[ .cond(4) 00 0 1101 S 0000 Rd(4) Rm(4) 0011 Rn(4) ]", mnemonic="LSR")
@ispec("32[ .cond(4) 00 0 0000 S Rd(4) 0000 Rm(4) 1001 Rn(4) ]", mnemonic="MUL")
@ispec("32[ .cond(4) 00 0 1101 S 0000 Rd(4) Rm(4) 0111 Rn(4) ]", mnemonic="ROR")
def A_default(obj, S, Rd, Rm, Rn):
    obj.setflags = S == 1
    if 15 in (Rd, Rm, Rn):
        raise InstructionError(obj)
    obj.d = env.regs[Rd]
    obj.m = env.regs[Rm]
    obj.n = env.regs[Rn]
    if obj.mnemonic != "MUL":
        obj.m = obj.m[0:8]
    obj.operands = [obj.d, obj.n, obj.m]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 1010 imm24(24) ]", mnemonic="B")
def A_label(obj, imm24):
    obj.imm32 = env.cst(imm24 << 2, 26).signextend(32)
    obj.operands = [obj.imm32]
    obj.type = type_control_flow


@ispec("32[ .cond(4) 0111110 msb(5) Rd(4) lsb(5) 001 Rn(4) ]", mnemonic="BFI")
@ispec("32[ .cond(4) 0111110 msb(5) Rd(4) lsb(5) 001 1111=Rn(4) ]", mnemonic="BFC")
def A_bits(obj, msb, Rd, lsb, Rn):
    if Rd == 15:
        raise InstructionError(obj)
    obj.d = env.regs[Rd]
    obj.msbit = msb
    obj.lsbit = lsb
    if obj.mnemonic == "BFC":
        obj.operands = [obj.d, obj.lsbit, obj.msbit - obj.lsbit + 1]
    else:
        obj.n = env.regs[Rn]
        obj.operands = [obj.d, obj.n, obj.lsbit, obj.msbit - obj.lsbit + 1]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 00010010 imm12(12) 0111 imm4(4) ]", mnemonic="BKPT")
def A_default(obj, imm12, imm4):
    obj.imm32 = env.cst((imm12 << 4) + imm4, 32)
    obj.operands = [obj.imm32]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 101 1 imm24(24) ]", mnemonic="BL")
def A_label(obj, imm24):
    obj.imm32 = env.cst(imm24 << 2, 26).signextend(32)
    obj.operands = [obj.imm32]
    obj.type = type_control_flow


@ispec("32[  1111    101 H imm24(24) ]", menmonic="BLX")
def A_label(obj, H, imm24):
    H = 2 * H
    obj.imm32 = env.cst((imm24 << 2) + H, 26).signextend(32)
    obj.operands = [obj.imm32]
    obj.type = type_control_flow


@ispec("32[ .cond(4) 00010010 1111 1111 1111 0011 Rm(4) ]", mnemonic="BLX")
@ispec("32[ .cond(4) 00010010 1111 1111 1111 0001 Rm(4) ]", mnemonic="BX")
@ispec("32[ .cond(4) 00010010 1111 1111 1111 0010 Rm(4) ]", mnemonic="BXJ")
def A_default(obj, Rm):
    if obj.mnemonic != "BX" and Rm == 15:
        raise InstructionError(obj)
    obj.m = env.regs[Rm]
    obj.operands = [obj.m]
    obj.type = type_control_flow


@ispec("32[ 1111 01010111 1111 1111 0000 0001 1111 ]", mnemonic="CLREX")
def A_default(obj):
    obj.operands = []
    obj.type = type_data_processing


@ispec("32[ .cond(4) 0011 0010 0000 1111 0000 00000000 ]", mnemonic="NOP")
@ispec("32[ .cond(4) 0011 0010 0000 1111 0000 00000001 ]", mnemonic="YIELD")
@ispec("32[ .cond(4) 0011 0010 0000 1111 0000 00000010 ]", mnemonic="WFE")
@ispec("32[ .cond(4) 0011 0010 0000 1111 0000 00000011 ]", mnemonic="WFI")
@ispec("32[ .cond(4) 0011 0010 0000 1111 0000 00000100 ]", mnemonic="SEV")
def A_default(obj):
    obj.type = type_cpu_state


@ispec("32[ .cond(4) 00010110 1111 Rd(4) 1111 0001 Rm(4) ]", mnemonic="CLZ")
def A_default(obj, Rd, Rm):
    if 15 in (Rd, Rm):
        raise InstructionError(obj)
    obj.d = env.regs[Rd]
    obj.m = env.regs[Rm]
    obj.operands = [obj.d, obj.n]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 00 1 1011 1 Rn(4) 0000 imm12(12) ]", mnemonic="CMN")
@ispec("32[ .cond(4) 00 1 1010 1 Rn(4) 0000 imm12(12) ]", mnemonic="CMP")
@ispec("32[ .cond(4) 00 1 1001 1 Rn(4) 0000 imm12(12) ]", mnemonic="TEQ")
@ispec("32[ .cond(4) 00 1 1000 1 Rn(4) 0000 imm12(12) ]", mnemonic="TST")
def A_default(obj, Rn, imm12):
    obj.n = env.regs[Rn]
    obj.imm32 = ARMExpandImm(imm12)
    obj.stype = None
    obj.operands = [obj.n, obj.imm32]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 00 0 1011 1 Rn(4) 0000 imm5(5) stype(2) 0 Rm(4) ]", mnemonic="CMN")
@ispec("32[ .cond(4) 00 0 1010 1 Rn(4) 0000 imm5(5) stype(2) 0 Rm(4) ]", mnemonic="CMP")
@ispec("32[ .cond(4) 00 0 1001 1 Rn(4) 0000 imm5(5) stype(2) 0 Rm(4) ]", mnemonic="TEQ")
@ispec("32[ .cond(4) 00 0 1000 1 Rn(4) 0000 imm5(5) stype(2) 0 Rm(4) ]", mnemonic="TST")
def A_sreg(obj, Rn, imm5, stype, Rm):
    obj.n = env.regs[Rn]
    obj.m = DecodeShift(stype, env.regs[Rm], env.cst(imm5, 5))
    obj.stype = stype
    obj.shift = imm5
    obj.m = env.regs[Rm]
    obj.operands = [obj.n, obj.m]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 00 0 1011 1 Rn(4) 0000 Rs(4) 0 stype(2) 1 Rm(4) ]", mnemonic="CMN")
@ispec("32[ .cond(4) 00 0 1010 1 Rn(4) 0000 Rs(4) 0 stype(2) 1 Rm(4) ]", mnemonic="CMP")
@ispec("32[ .cond(4) 00 0 1001 1 Rn(4) 0000 Rs(4) 0 stype(2) 1 Rm(4) ]", mnemonic="TEQ")
@ispec("32[ .cond(4) 00 0 1000 1 Rn(4) 0000 Rs(4) 0 stype(2) 1 Rm(4) ]", mnemonic="TST")
def A_sreg(obj, Rn, Rs, stype, Rm):
    if 15 in (Rn, Rm, Rs):
        raise InstructionError(obj)
    obj.n = env.regs[Rn]
    obj.m = DecodeShift(stype, env.regs[Rm], env.regs[Rs])
    obj.stype = None
    obj.m = env.regs[Rm]
    obj.operands = [obj.n, obj.m]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 00110010 0000 1111 0000 1111 .option(4) ]", mnemonic="DBG")
@ispec("32[  1111    01010111 1111 1111 0000 0101 .option(4) ]", mnemonic="DMB")
@ispec("32[  1111    01010111 1111 1111 0000 0100 .option(4) ]", mnemonic="DSB")
@ispec("32[  1111    01010111 1111 1111 0000 0110 .option(4) ]", mnemonic="ISB")
def A_default(obj):
    obj.operands = []
    obj.type = type_cpu_state


@ispec("32[ .cond(4) 100010 W 1 Rn(4) ~register_list(16) ]", mnemonic="LDM")
@ispec("32[ .cond(4) 100000 W 1 Rn(4) ~register_list(16) ]", mnemonic="LDMDA")
@ispec("32[ .cond(4) 100100 W 1 Rn(4) ~register_list(16) ]", mnemonic="LDMDB")
@ispec("32[ .cond(4) 100110 W 1 Rn(4) ~register_list(16) ]", mnemonic="LDMIB")
@ispec("32[ .cond(4) 100010 W 0 Rn(4) ~register_list(16) ]", mnemonic="STM")
@ispec("32[ .cond(4) 100000 W 0 Rn(4) ~register_list(16) ]", mnemonic="STMDA")
@ispec("32[ .cond(4) 100100 W 0 Rn(4) ~register_list(16) ]", mnemonic="STMDB")
@ispec("32[ .cond(4) 100110 W 0 Rn(4) ~register_list(16) ]", mnemonic="STMIB")
def A_reglist(obj, W, Rn, register_list):
    obj.n = env.regs[Rn]
    obj.registers = [env.regs[i] for i, r in enumerate(register_list) if r == 1]
    obj.wback = W == 1
    if Rn == 15 or len(obj.registers) < 1:
        raise InstructionError(obj)
    if obj.wback and (obj.n in obj.registers):
        raise InstructionError(obj)
    obj.operands = [obj.n, obj.registers]
    obj.type = type_data_processing
    if env.pc in obj.registers:
        obj.type = type_control_flow


@ispec("32[ .cond(4) 010 P U 0 W 1 Rn(4) Rt(4) imm12(12) ]", mnemonic="LDR")
@ispec("32[ .cond(4) 010 P U 1 W 1 Rn(4) Rt(4) imm12(12) ]", mnemonic="LDRB")
@ispec("32[ .cond(4) 010 P U 0 W 0 Rn(4) Rt(4) imm12(12) ]", mnemonic="STR")
@ispec("32[ .cond(4) 010 P U 1 W 0 Rn(4) Rt(4) imm12(12) ]", mnemonic="STRB")
@ispec("32[ .cond(4) 010 0=P U 0 1=W 1 Rn(4) Rt(4) imm12(12) ]", mnemonic="LDRT")
@ispec("32[ .cond(4) 010 0=P U 1 1=W 1 Rn(4) Rt(4) imm12(12) ]", mnemonic="LDRBT")
@ispec("32[ .cond(4) 010 0=P U 0 1=W 0 Rn(4) Rt(4) imm12(12) ]", mnemonic="STRT")
@ispec("32[ .cond(4) 010 0=P U 1 1=W 0 Rn(4) Rt(4) imm12(12) ]", mnemonic="STRBT")
def A_deref(obj, P, U, W, Rn, Rt, imm12):
    obj.n = env.regs[Rn]
    obj.t = env.regs[Rt]
    obj.imm32 = env.cst(imm12, 32)
    if Rn == 15:
        if not (P == 1 and W == 0):
            raise InstructionError(obj)
    if P == 0 and W == 1:
        obj.postindex = True
        obj.register_form = False
        if (15 in (Rt, Rn)) or (Rn == Rt):
            raise InstructionError(obj)
    else:
        obj.index = P == 1
        obj.wback = (P == 0) | (W == 1)
        if obj.wback and Rn == Rt:
            raise InstructionError(obj)
    obj.add = U == 1
    obj.operands = [obj.t, obj.n, obj.imm32]
    obj.type = type_data_processing
    if obj.t == env.pc:
        obj.type = type_control_flow


@ispec(
    "32[ .cond(4) 011   P U 0   W 1 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]",
    mnemonic="LDR",
)
@ispec(
    "32[ .cond(4) 011   P U 1   W 1 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]",
    mnemonic="LDRB",
)
@ispec(
    "32[ .cond(4) 011   P U 0   W 0 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]",
    mnemonic="STR",
)
@ispec(
    "32[ .cond(4) 011   P U 1   W 0 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]",
    mnemonic="STRB",
)
@ispec(
    "32[ .cond(4) 011 0=P U 0 1=W 1 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]",
    mnemonic="LDRT",
)
@ispec(
    "32[ .cond(4) 011 0=P U 1 1=W 1 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]",
    mnemonic="LDRBT",
)
@ispec(
    "32[ .cond(4) 011 0=P U 0 1=W 0 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]",
    mnemonic="STRT",
)
@ispec(
    "32[ .cond(4) 011 0=P U 1 1=W 0 Rn(4) Rt(4) imm5(5) stype(2) 0 Rm(4) ]",
    mnemonic="STRBT",
)
def A_deref(obj, P, U, W, Rn, Rt, imm5, stype, Rm):
    obj.n = env.regs[Rn]
    obj.t = env.regs[Rt]
    obj.m = DecodeShift(stype, env.regs[Rm], imm5)
    if Rn == 15:
        if not (P == 1 and W == 0):
            raise InstructionError(obj)
    if P == 0 and W == 1:
        obj.postindex = True
        obj.register_form = True
        if (15 in (Rt, Rn, Rm)) or (Rn == Rt):
            raise InstructionError(obj)
    else:
        obj.index = P == 1
        obj.wback = (P == 0) | (W == 1)
        if Rm == 15:
            raise InstructionError(obj)
        if obj.wback and (Rn == 15 or Rn == Rt):
            raise InstructionError(obj)
    obj.add = U == 1
    obj.operands = [obj.t, obj.n, obj.m]
    obj.type = type_data_processing
    if obj.t == env.pc:
        obj.type = type_control_flow


@ispec(
    "32[ .cond(4) 000 P U 1 W 0 Rn(4) Rt(4) imm4H(4) 1101 imm4L(4) ]", mnemonic="LDRD"
)
@ispec(
    "32[ .cond(4) 000 P U 1 W 0 Rn(4) Rt(4) imm4H(4) 1111 imm4L(4) ]", mnemonic="STRD"
)
def A_deref(obj, P, U, W, Rn, Rt, imm4H, imm4L):
    obj.n = env.regs[Rn]
    obj.t = env.regs[Rt]
    obj.t2 = env.regs[Rt + 1]
    if Rt == 14 or Rt % 2 == 1:
        raise InstructionError(obj)
    obj.imm32 = env.cst((imm4H << 4) + imm4L, 32)
    obj.index = P == 1
    obj.wback = (P == 0) | (W == 1)
    obj.add = U == 1
    if obj.wback and (Rn == 15 or Rn == Rt or Rn == Rt + 1):
        raise InstructionError(obj)
    obj.operands = [obj.t, obj.t2, obj.n, obj.imm32]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 000 P U 0 W 0 Rn(4) Rt(4) 0000 1101 Rm(4) ]", mnemonic="LDRD")
@ispec("32[ .cond(4) 000 P U 0 W 0 Rn(4) Rt(4) 0000 1111 Rm(4) ]", mnemonic="STRD")
def A_deref(obj, P, U, W, Rn, Rt, Rm):
    obj.n = env.regs[Rn]
    obj.t = env.regs[Rt]
    obj.m = env.regs[Rm]
    obj.t2 = env.regs[Rt + 1]
    if P == 0 and W == 1:
        raise InstructionError(obj)
    if Rt == 14 or Rm == 15:
        raise InstructionError(obj)
    if Rn == 15:
        if not (P == 1 and W == 0):
            raise InstructionError(obj)
    obj.index = P == 1
    obj.wback = (P == 0) | (W == 1)
    if obj.wback and (Rn == 15 or Rn == Rt or Rn == Rt + 1):
        raise InstructionError(obj)
    obj.add = U == 1
    obj.operands = [obj.t, obj.t2, obj.n, obj.m]
    obj.type = type_data_processing


@ispec(
    "32[ .cond(4) 0001100 1 Rn(4) Rt(4) 1111 1001 1111 ]",
    mnemonic="LDREX",
    imm32=env.cst(0, 32),
)
@ispec("32[ .cond(4) 0001110 1 Rn(4) Rt(4) 1111 1001 1111 ]", mnemonic="LDREXB")
@ispec("32[ .cond(4) 0001101 1 Rn(4) Rt(4) 1111 1001 1111 ]", mnemonic="LDREXD")
@ispec("32[ .cond(4) 0001111 1 Rn(4) Rt(4) 1111 1001 1111 ]", mnemonic="LDREXH")
def A_default(obj, Rn, Rt):
    obj.n = env.regs[Rn]
    obj.t = env.regs[Rt]
    if Rn == 15 or Rt == 15:
        raise InstructionError(obj)
    obj.operands = [obj.t, obj.n]
    if obj.mnemonic == "LDREXD":
        obj.t2 = env.regs[Rt + 1]
        obj.operands.insert(2, obj.t2)
    obj.type = type_data_processing


@ispec(
    "32[ .cond(4) 0001100 0 Rn(4) Rd(4) 1111 1001 Rt(4) ]",
    mnemonic="STREX",
    imm32=env.cst(0, 32),
)
@ispec("32[ .cond(4) 0001110 0 Rn(4) Rd(4) 1111 1001 Rt(4) ]", mnemonic="STREXB")
@ispec("32[ .cond(4) 0001101 0 Rn(4) Rd(4) 1111 1001 Rt(4) ]", mnemonic="STREXD")
@ispec("32[ .cond(4) 0001111 0 Rn(4) Rd(4) 1111 1001 Rt(4) ]", mnemonic="STREXH")
def A_default(obj, Rn, Rd, Rt):
    if 15 in (Rt, Rn, Rd):
        raise InstructionError(obj)
    if Rn == Rd or Rd == Rt:
        raise InstructionError(obj)
    obj.d = env.regs[Rd]
    obj.n = env.regs[Rn]
    obj.t = env.regs[Rt]
    obj.operands = [obj.d, obj.t, obj.n]
    if obj.mnemonic == "STREXD":
        obj.t2 = env.regs[Rt + 1]
        obj.operands.insert(2, obj.t2)
    obj.type = type_data_processing


@ispec(
    "32[ .cond(4) 000   P U 1   W 1 Rn(4) Rt(4) imm4H(4) 1011 imm4L(4) ]",
    mnemonic="LDRH",
)
@ispec(
    "32[ .cond(4) 000   P U 1   W 1 Rn(4) Rt(4) imm4H(4) 1101 imm4L(4) ]",
    mnemonic="LDRSB",
)
@ispec(
    "32[ .cond(4) 000   P U 1   W 1 Rn(4) Rt(4) imm4H(4) 1111 imm4L(4) ]",
    mnemonic="LDRSH",
)
@ispec(
    "32[ .cond(4) 000   P U 1   W 0 Rn(4) Rt(4) imm4H(4) 1011 imm4L(4) ]",
    mnemonic="STRH",
)
@ispec(
    "32[ .cond(4) 000 0=P U 1 1=W 1 Rn(4) Rt(4) imm4H(4) 1011 imm4L(4) ]",
    mnemonic="LDRHT",
)
@ispec(
    "32[ .cond(4) 000 0=P U 1 1=W 1 Rn(4) Rt(4) imm4H(4) 1101 imm4L(4) ]",
    mnemonic="LDRSBT",
)
@ispec(
    "32[ .cond(4) 000 0=P U 1 1=W 1 Rn(4) Rt(4) imm4H(4) 1111 imm4L(4) ]",
    mnemonic="LDRSHT",
)
@ispec(
    "32[ .cond(4) 000 0=P U 1 1=W 0 Rn(4) Rt(4) imm4H(4) 1011 imm4L(4) ]",
    mnemonic="STRHT",
)
def A_deref(obj, P, U, W, Rn, Rt, imm4H, imm4L):
    obj.n = env.regs[Rn]
    obj.t = env.regs[Rt]
    obj.imm32 = env.cst((imm4H << 4) + imm4L, 32)
    if P == 0 and W == 1:
        obj.postindex = True
        obj.register_form = False
        if (15 in (Rt, Rn)) or (Rn == Rt):
            raise InstructionError(obj)
    else:
        obj.index = P == 1
        obj.wback = (P == 0) | (W == 1)
        if Rt == 15 or (obj.wback and Rn == Rt):
            raise InstructionError(obj)
    obj.add = U == 1
    obj.operands = [obj.t, obj.n, obj.imm32]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 000   P U 0   W 1 Rn(4) Rt(4) 0000 1011 Rm(4) ]", mnemonic="LDRH")
@ispec("32[ .cond(4) 000   P U 0   W 1 Rn(4) Rt(4) 0000 1101 Rm(4) ]", mnemonic="LDRSB")
@ispec("32[ .cond(4) 000   P U 0   W 1 Rn(4) Rt(4) 0000 1111 Rm(4) ]", mnemonic="LDRSH")
@ispec("32[ .cond(4) 000   P U 0   W 0 Rn(4) Rt(4) 0000 1011 Rm(4) ]", mnemonic="STRH")
@ispec("32[ .cond(4) 000 0=P U 0 1=W 1 Rn(4) Rt(4) 0000 1011 Rm(4) ]", mnemonic="LDRHT")
@ispec(
    "32[ .cond(4) 000 0=P U 0 1=W 1 Rn(4) Rt(4) 0000 1101 Rm(4) ]", mnemonic="LDRSBT"
)
@ispec(
    "32[ .cond(4) 000 0=P U 0 1=W 1 Rn(4) Rt(4) 0000 1111 Rm(4) ]", mnemonic="LDRSHT"
)
@ispec("32[ .cond(4) 000 0=P U 0 1=W 0 Rn(4) Rt(4) 0000 1011 Rm(4) ]", mnemonic="STRHT")
def A_deref(obj, P, U, W, Rn, Rt, Rm):
    obj.n = env.regs[Rn]
    obj.t = env.regs[Rt]
    obj.m = env.regs[Rm]
    if P == 0 and W == 1:
        obj.postindex = True
        obj.register_form = True
        if (15 in (Rt, Rn, Rm)) or (Rn == Rt):
            raise InstructionError(obj)
    else:
        obj.index = P == 1
        obj.wback = (P == 0) | (W == 1)
        if Rt == 15 or Rm == 15:
            raise InstructionError(obj)
        if obj.wback and (Rn == 15 or Rn == Rt):
            raise InstructionError(obj)
    obj.add = U == 1
    obj.operands = [obj.t, obj.n, obj.m]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 0000001 S Rd(4) Ra(4) Rm(4) 1001 Rn(4) ]", mnemonic="MLA")
def A_default(obj, S, Rd, Ra, Rm, Rn):
    obj.setflags = S == 1
    obj.d = env.regs[Rd]
    obj.n = env.regs[Rn]
    obj.m = env.regs[Rm]
    obj.a = env.regs[Ra]
    if 15 in (Rd, Rn, Rm, Ra):
        raise InstructionError(obj)
    obj.operands = [obj.d, obj.n, obj.m, obj.a]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 0011 0000 imm4(4) Rd(4) imm12(12) ]", mnemonic="MOVW")
def A_default(obj, imm4, Rd, imm12):
    obj.setflags = False
    obj.d = env.regs[Rd]
    obj.imm32 = ARMExpandImm((imm4 << 12) + imm12)
    obj.operands = [obj.d, obj.imm32]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 00 0 1101 S 0000 Rd(4) 00000 000 Rm(4) ]", mnemonic="MOV")
@ispec("32[ .cond(4) 00 0 1101 S 0000 Rd(4) 00000 110 Rm(4) ]", mnemonic="RRX")
def A_default(obj, S, Rd, Rm):
    obj.setflags = S == 1
    obj.d = env.regs[Rd]
    obj.m = env.regs[Rm]
    obj.operands = [obj.d, obj.m]
    obj.type = type_data_processing
    if obj.d == env.pc:
        obj.type = type_control_flow


@ispec("32[ .cond(4) 0011 0100 imm4(4) Rd(4) imm12(12) ]", mnemonic="MOVT")
def A_default(obj, imm4, Rd, imm12):
    obj.d = env.regs[Rd]
    if Rd == 15:
        raise InstructionError(obj)
    obj.imm16 = env.cst((imm4 << 12) + imm12, 16)
    obj.operands = [obj.d, obj.imm16]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 00010000 1111 Rd(4) 0000 0000 0000 ]", mnemonic="MRS")
def A_default(obj, Rd):
    obj.d = env.regs[Rd]
    if Rd == 15:
        raise InstructionError(obj)
    obj.operands = [obj.d, env.apsr]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 00110010 ~mask(2) 00 1111 imm12(12) ]", mnemonic="MSR")
def instr_MSR(obj, mask, imm12):
    obj.imm32 = ARMExpandImm(imm12)
    obj.write_nzcvq = mask[1] == 1
    obj.write_g = mask[0] == 1
    obj.operands = [obj.imm32]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 00010 0 10 ~mask(2) 00 1111 0000 0000 Rn(4) ]", mnemonic="MSR")
def instr_MSR(obj, mask, Rn):
    obj.n = env.regs[Rn]
    obj.write_nzcvq = mask[1] == 1
    obj.write_g = mask[0] == 1
    obj.operands = [obj.n]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 00 0 1111 S 0000 Rd(4) imm5(5) stype(2) 0 Rm(4) ]", mnemonic="MVN")
def A_sreg(obj, S, Rd, imm5, stype, Rm):
    obj.setflags = S == 1
    obj.d = env.regs[Rd]
    obj.m = DecodeShift(stype, env.regs[Rm], imm5)
    obj.operands = [obj.d, obj.m]
    obj.type = type_data_processing
    if obj.d == env.pc:
        obj.type = type_control_flow


@ispec("32[ .cond(4) 00 0 1111 S 0000 Rd(4) Rs(4) 0 stype(2) 1 Rm(4) ]", mnemonic="MVN")
def A_sreg(obj, S, Rd, Rs, stype, Rm):
    obj.setflags = S == 1
    obj.d = env.regs[Rd]
    obj.m = DecodeShift(stype, env.regs[Rm], env.regs[Rs])
    if 15 in (Rd, Rm, Rs):
        raise InstructionError(obj)
    obj.operands = [obj.d, obj.m]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 01101000 Rn(4) Rd(4) imm5(5) 0=tb 01 Rm(4) ]", mnemonic="PKHBT")
@ispec("32[ .cond(4) 01101000 Rn(4) Rd(4) imm5(5) 1=tb 01 Rm(4) ]", mnemonic="PKHTB")
def A_sreg(obj, Rn, Rd, imm5, tb, Rm):
    obj.n = env.regs[Rn]
    obj.d = env.regs[Rd]
    if 15 in (Rd, Rn, Rm):
        raise InstructionError(obj)
    obj.m = DecodeShift(tb < 1, env.regs[Rm], env.cst(imm5, 5))
    obj.operands = [obj.d, obj.n, obj.m]
    obj.type = type_data_processing


@ispec("32[ 1111 01 0 1 U 1=R 01 Rn(4) 1111 imm12(12) ]", mnemonic="PLD")
@ispec("32[ 1111 01 0 1 U 0=R 01 Rn(4) 1111 imm12(12) ]", mnemonic="PLDW")
def instr_PLx(obj, U, R, Rn, imm12):
    obj.n = env.regs[Rn]
    obj.imm32 = env.cst(imm12, 32)
    obj.add = U == 1
    obj.is_pldw = R == 0
    obj.operands = [obj.n, obj.imm32]
    obj.type = type_cpu_state


@ispec("32[ 1111 01 1 1 U 1=R 01 Rn(4) 1111 imm5(5) stype(2) 0 Rm(4) ]", mnemonic="PLD")
@ispec(
    "32[ 1111 01 1 1 U 0=R 01 Rn(4) 1111 imm5(5) stype(2) 0 Rm(4) ]", mnemonic="PLDW"
)
def instr_PLx(obj, U, R, Rn, imm5, stype, Rm):
    obj.n = env.regs[Rn]
    obj.m = DecodeShift(stype, env.regs[Rm], env.cst(imm5, 5))
    if Rm == 15:
        raise InstructionError(obj)
    obj.add = U == 1
    obj.is_pldw = R == 0
    obj.operands = [obj.n, obj.m]
    obj.type = type_cpu_state


@ispec("32[ 1111 0100 U 101 Rn(4) 1111 imm12(12) ]", mnemonic="PLI")
def instr_PLx(obj, U, Rn, imm12):
    obj.n = env.regs[Rn]
    obj.imm32 = env.cst(imm12, 32)
    obj.add = U == 1
    obj.operands = [obj.n, obj.imm32]
    obj.type = type_cpu_state


@ispec("32[ 1111 0110 U 101 Rn(4) 1111 imm5(5) stype(2) 0 Rm(4) ]", mnemonic="PLI")
def instr_PLx(obj, U, Rn, imm5, stype, Rm):
    obj.n = env.regs[Rn]
    obj.m = DecodeShift(stype, env.regs[Rm], env.cst(imm5, 5))
    obj.add = U == 1
    obj.operands = [obj.n, obj.m]
    obj.type = type_cpu_state


@ispec("32[ .cond(4) 010100101101 Rt(4) 000000000100 ]", mnemonic="PUSH")
@ispec("32[ .cond(4) 010010011101 Rt(4) 000000000100 ]", mnemonic="POP")
def A_reglist(obj, Rt):
    obj.t = env.regs[Rt]
    if Rt == 13:
        raise InstructionError(obj)
    obj.registers = [obj.t]
    obj.operands = [obj.registers]
    obj.type = type_data_processing
    if obj.mnemonic == "POP":
        if env.pc in obj.registers:
            obj.type = type_control_flow


@ispec("32[ .cond(4) 10010010 1101 ~register_list(16) ]", mnemonic="PUSH")
@ispec("32[ .cond(4) 10001011 1101 ~register_list(16) ]", mnemonic="POP")
def A_reglist(obj, register_list):
    obj.registers = [env.regs[i] for i, r in enumerate(register_list) if r == 1]
    if env.regs[13] in obj.registers:
        raise InstructionError(obj)
    obj.operands = [obj.registers]
    obj.type = type_data_processing
    if obj.mnemonic == "POP":
        if env.pc in obj.registers:
            obj.type = type_control_flow


@ispec("32[ .cond(4) 00010000 Rn(4) Rd(4) 0000 0101 Rm(4) ]", mnemonic="QADD")
@ispec("32[ .cond(4) 00010010 Rn(4) Rd(4) 0000 0101 Rm(4) ]", mnemonic="QSUB")
@ispec("32[ .cond(4) 00010100 Rn(4) Rd(4) 0000 0101 Rm(4) ]", mnemonic="QDADD")
@ispec("32[ .cond(4) 00010110 Rn(4) Rd(4) 0000 0101 Rm(4) ]", mnemonic="QDSUB")
def A_default(obj, Rn, Rd, Rm):
    obj.n = env.regs[Rn]
    obj.d = env.regs[Rd]
    obj.m = env.regs[Rm]
    if 15 in (Rd, Rm, Rn):
        raise InstructionError(obj)
    obj.operands = [obj.d, obj.m, obj.n]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 01100001 Rn(4) Rd(4) 1111 0001 Rm(4) ]", mnemonic="SADD16")
@ispec("32[ .cond(4) 01100001 Rn(4) Rd(4) 1111 1001 Rm(4) ]", mnemonic="SADD8")
@ispec("32[ .cond(4) 01100001 Rn(4) Rd(4) 1111 0011 Rm(4) ]", mnemonic="SASX")
@ispec("32[ .cond(4) 01100001 Rn(4) Rd(4) 1111 0101 Rm(4) ]", mnemonic="SSASX")
@ispec("32[ .cond(4) 01100001 Rn(4) Rd(4) 1111 0111 Rm(4) ]", mnemonic="SSUB16")
@ispec("32[ .cond(4) 01100001 Rn(4) Rd(4) 1111 1111 Rm(4) ]", mnemonic="SSUB8")
@ispec("32[ .cond(4) 01100010 Rn(4) Rd(4) 1111 0001 Rm(4) ]", mnemonic="QADD16")
@ispec("32[ .cond(4) 01100010 Rn(4) Rd(4) 1111 1001 Rm(4) ]", mnemonic="QADD8")
@ispec("32[ .cond(4) 01100010 Rn(4) Rd(4) 1111 0011 Rm(4) ]", mnemonic="QASX")
@ispec("32[ .cond(4) 01100010 Rn(4) Rd(4) 1111 0101 Rm(4) ]", mnemonic="QSAX")
@ispec("32[ .cond(4) 01100010 Rn(4) Rd(4) 1111 0111 Rm(4) ]", mnemonic="QSUB16")
@ispec("32[ .cond(4) 01100010 Rn(4) Rd(4) 1111 1111 Rm(4) ]", mnemonic="QSUB8")
@ispec("32[ .cond(4) 01100011 Rn(4) Rd(4) 1111 0001 Rm(4) ]", mnemonic="SHADD16")
@ispec("32[ .cond(4) 01100011 Rn(4) Rd(4) 1111 1001 Rm(4) ]", mnemonic="SHADD8")
@ispec("32[ .cond(4) 01100011 Rn(4) Rd(4) 1111 0011 Rm(4) ]", mnemonic="SHASX")
@ispec("32[ .cond(4) 01100011 Rn(4) Rd(4) 1111 0101 Rm(4) ]", mnemonic="SHSAX")
@ispec("32[ .cond(4) 01100011 Rn(4) Rd(4) 1111 0111 Rm(4) ]", mnemonic="SHSUB16")
@ispec("32[ .cond(4) 01100011 Rn(4) Rd(4) 1111 1111 Rm(4) ]", mnemonic="SHSUB8")
@ispec("32[ .cond(4) 01100101 Rn(4) Rd(4) 1111 0001 Rm(4) ]", mnemonic="UADD16")
@ispec("32[ .cond(4) 01100101 Rn(4) Rd(4) 1111 1001 Rm(4) ]", mnemonic="UADD8")
@ispec("32[ .cond(4) 01100101 Rn(4) Rd(4) 1111 0011 Rm(4) ]", mnemonic="UASX")
@ispec("32[ .cond(4) 01100110 Rn(4) Rd(4) 1111 0001 Rm(4) ]", mnemonic="UQADD16")
@ispec("32[ .cond(4) 01100110 Rn(4) Rd(4) 1111 0011 Rm(4) ]", mnemonic="UQASX")
@ispec("32[ .cond(4) 01100110 Rn(4) Rd(4) 1111 0101 Rm(4) ]", mnemonic="UQSAX")
@ispec("32[ .cond(4) 01100110 Rn(4) Rd(4) 1111 0111 Rm(4) ]", mnemonic="UQSUB16")
@ispec("32[ .cond(4) 01100110 Rn(4) Rd(4) 1111 1111 Rm(4) ]", mnemonic="UQSUB8")
@ispec("32[ .cond(4) 01100110 Rn(4) Rd(4) 1111 1001 Rm(4) ]", mnemonic="UQADD8")
@ispec("32[ .cond(4) 01100111 Rn(4) Rd(4) 1111 0001 Rm(4) ]", mnemonic="UHADD16")
@ispec("32[ .cond(4) 01100111 Rn(4) Rd(4) 1111 1001 Rm(4) ]", mnemonic="UHADD8")
@ispec("32[ .cond(4) 01100111 Rn(4) Rd(4) 1111 0011 Rm(4) ]", mnemonic="UHASX")
@ispec("32[ .cond(4) 01100111 Rn(4) Rd(4) 1111 0101 Rm(4) ]", mnemonic="UHSAX")
@ispec("32[ .cond(4) 01100111 Rn(4) Rd(4) 1111 0111 Rm(4) ]", mnemonic="UHSUB16")
@ispec("32[ .cond(4) 01100111 Rn(4) Rd(4) 1111 1111 Rm(4) ]", mnemonic="UHSUB8")
@ispec("32[ .cond(4) 01101000 Rn(4) Rd(4) 1111 1011 Rm(4) ]", mnemonic="SEL")
@ispec("32[ .cond(4) 01100101 Rn(4) Rd(4) 1111 0101 Rm(4) ]", mnemonic="USAX")
@ispec("32[ .cond(4) 01100101 Rn(4) Rd(4) 1111 0111 Rm(4) ]", mnemonic="USUB16")
@ispec("32[ .cond(4) 01100101 Rn(4) Rd(4) 1111 1111 Rm(4) ]", mnemonic="USUB8")
def A_default(obj, Rn, Rd, Rm):
    obj.n = env.regs[Rn]
    obj.d = env.regs[Rd]
    obj.m = env.regs[Rm]
    if 15 in (Rd, Rm, Rn):
        raise InstructionError(obj)
    obj.operands = [obj.d, obj.n, obj.m]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 01101111 1111 Rd(4) 1111 0011 Rm(4) ]", mnemonic="RBIT")
@ispec("32[ .cond(4) 01101011 1111 Rd(4) 1111 0011 Rm(4) ]", mnemonic="REV")
@ispec("32[ .cond(4) 01101011 1111 Rd(4) 1111 1011 Rm(4) ]", mnemonic="REV16")
@ispec("32[ .cond(4) 01101111 1111 Rd(4) 1111 1011 Rm(4) ]", mnemonic="REVSH")
def A_default(obj, Rd, Rm):
    obj.d = env.regs[Rd]
    obj.m = env.regs[Rm]
    if 15 in (Rd, Rm):
        raise InstructionError(obj)
    obj.operands = [obj.d, obj.m]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 01111 01 widthm1(5) Rd(4) lsb(5) 101 Rn(4) ]", mnemonic="SBFX")
@ispec("32[ .cond(4) 01111 11 widthm1(5) Rd(4) lsb(5) 101 Rn(4) ]", mnemonic="UBFX")
def A_default(obj, widthm1, Rd, lsb, Rn):
    obj.d = env.regs[Rd]
    obj.n = env.regs[Rn]
    if 15 in (Rd, Rn):
        raise InstructionError(obj)
    obj.lsbit = env.cst(lsb, 5)
    obj.widthminus1 = env.cst(widthm1, 5)
    obj.operands = [obj.d, obj.n, obj.lsbit, obj.widthminus1 + 1]
    obj.type = type_data_processing


@ispec("32[ 1111 00010000 000 1 000000 E 0 0000 0000 ]", mnemonic="SETEND")
def instr_SETEND(obj, E):
    obj.set_bigend = E == 1
    obj.type = type_cpu_state


@ispec("32[ .cond(4) 00000110 Rd(4) Ra(4) Rm(4) 1001 Rn(4) ]", mnemonic="MLS")
@ispec("32[ .cond(4) 00010000 Rd(4) Ra(4) Rm(4) 1000 Rn(4) ]", mnemonic="SMLABB")
@ispec("32[ .cond(4) 00010000 Rd(4) Ra(4) Rm(4) 1010 Rn(4) ]", mnemonic="SMLATB")
@ispec("32[ .cond(4) 00010000 Rd(4) Ra(4) Rm(4) 1100 Rn(4) ]", mnemonic="SMLABT")
@ispec("32[ .cond(4) 00010000 Rd(4) Ra(4) Rm(4) 1110 Rn(4) ]", mnemonic="SMLATT")
@ispec("32[ .cond(4) 01110000 Rd(4) Ra(4) Rm(4) 0001 Rn(4) ]", mnemonic="SMLAD")
@ispec("32[ .cond(4) 01110000 Rd(4) Ra(4) Rm(4) 0011 Rn(4) ]", mnemonic="SMLADX")
@ispec("32[ .cond(4) 00010010 Rd(4) Ra(4) Rm(4) 1000 Rn(4) ]", mnemonic="SMLAWB")
@ispec("32[ .cond(4) 00010010 Rd(4) Ra(4) Rm(4) 1100 Rn(4) ]", mnemonic="SMLAWT")
@ispec("32[ .cond(4) 01110000 Rd(4) Ra(4) Rm(4) 0101 Rn(4) ]", mnemonic="SMLSD")
@ispec("32[ .cond(4) 01110000 Rd(4) Ra(4) Rm(4) 0111 Rn(4) ]", mnemonic="SMLSDX")
@ispec("32[ .cond(4) 01110101 Rd(4) Ra(4) Rm(4) 0001 Rn(4) ]", mnemonic="SMMLA")
@ispec("32[ .cond(4) 01110101 Rd(4) Ra(4) Rm(4) 0011 Rn(4) ]", mnemonic="SMMLAR")
@ispec("32[ .cond(4) 01110101 Rd(4) Ra(4) Rm(4) 1101 Rn(4) ]", mnemonic="SMMLS")
@ispec("32[ .cond(4) 01110101 Rd(4) Ra(4) Rm(4) 1111 Rn(4) ]", mnemonic="SMMLSR")
@ispec("32[ .cond(4) 01111000 Rd(4) Ra(4) Rm(4) 0001 Rn(4) ]", mnemonic="USADA8")
def A_default(obj, Rd, Ra, Rm, Rn):
    obj.d = env.regs[Rd]
    obj.n = env.regs[Rn]
    obj.m = env.regs[Rm]
    obj.a = env.regs[Ra]
    if 15 in (Rd, Rn, Rm, Ra):
        raise InstructionError(obj)
    obj.operands = [obj.d, obj.n, obj.m, obj.a]
    obj.type = type_data_processing


@ispec("32[ .cond(4) 0000111 S RdHi(4) RdLo(4) Rm(4) 1001 Rn(4) ]", mnemonic="SMLAL")
@ispec("32[ .cond(4) 0000110 S RdHi(4) RdLo(4) Rm(4) 1001 Rn(4) ]", mnemonic="SMULL")
@ispec("32[ .cond(4) 0000101 S RdHi(4) RdLo(4) Rm(4) 1001 Rn(4) ]", mnemonic="UMLAL")
@ispec("32[ .cond(4) 0000100 S RdHi(4) RdLo(4) Rm(4) 1001 Rn(4) ]", mnemonic="UMULL")
def A_default(obj, S, RdHi, RdLo, Rm, Rn):
    obj.setflags = S == 1
    obj.dLo = env.regs[RdLo]
    obj.dHi = env.regs[RdHi]
    obj.m = env.regs[Rm]
    obj.n = env.regs[Rn]
    obj.operands = [obj.dLo, obj.dHi, obj.n, obj.m]
    if env.pc in obj.operands:
        raise InstructionError(obj)
    obj.type = type_data_processing


@ispec("32[ .cond(4) 00010100 RdHi(4) RdLo(4) Rm(4) 1000 Rn(4) ]", mnemonic="SMLALBB")
@ispec("32[ .cond(4) 00010100 RdHi(4) RdLo(4) Rm(4) 1010 Rn(4) ]", mnemonic="SMLALTB")
@ispec("32[ .cond(4) 00010100 RdHi(4) RdLo(4) Rm(4) 1100 Rn(4) ]", mnemonic="SMLALBT")
@ispec("32[ .cond(4) 00010100 RdHi(4) RdLo(4) Rm(4) 1110 Rn(4) ]", mnemonic="SMLALTT")
@ispec("32[ .cond(4) 01110100 RdHi(4) RdLo(4) Rm(4) 0001 Rn(4) ]", mnemonic="SMLALD")
@ispec("32[ .cond(4) 01110100 RdHi(4) RdLo(4) Rm(4) 0011 Rn(4) ]", mnemonic="SMLALDX")
@ispec("32[ .cond(4) 01110100 RdHi(4) RdLo(4) Rm(4) 0101 Rn(4) ]", mnemonic="SMLSLD")
@ispec("32[ .cond(4) 01110100 RdHi(4) RdLo(4) Rm(4) 0111 Rn(4) ]", mnemonic="SMLSLDX")
@ispec("32[ .cond(4) 00000100 RdHi(4) RdLo(4) Rm(4) 1001 Rn(4) ]", mnemonic="UMAAL")
def A_default(obj, RdHi, RdLo, Rm, Rn):
    obj.dLo = env.regs[RdLo]
    obj.dHi = env.regs[RdHi]
    obj.m = env.regs[Rm]
    obj.n = env.regs[Rn]
    obj.operands = [obj.dLo, obj.dHi, obj.n, obj.m]
    if env.pc in obj.operands:
        raise InstructionError(obj)
    obj.type = type_data_processing


@ispec("32[ .cond(4) 01110101 Rd(4) 1111 Rm(4) 0001 Rn(4) ]", mnemonic="SMMUL")
@ispec("32[ .cond(4) 01110101 Rd(4) 1111 Rm(4) 0011 Rn(4) ]", mnemonic="SMMULR")
@ispec("32[ .cond(4) 01110000 Rd(4) 1111 Rm(4) 0001 Rn(4) ]", mnemonic="SMUAD")
@ispec("32[ .cond(4) 01110000 Rd(4) 1111 Rm(4) 0011 Rn(4) ]", mnemonic="SMUADX")
@ispec("32[ .cond(4) 01110000 Rd(4) 1111 Rm(4) 0101 Rn(4) ]", mnemonic="SMUSD")
@ispec("32[ .cond(4) 01110000 Rd(4) 1111 Rm(4) 0111 Rn(4) ]", mnemonic="SMUSDX")
@ispec("32[ .cond(4) 00010110 Rd(4) 1111 Rm(4) 1000 Rn(4) ]", mnemonic="SMULBB")
@ispec("32[ .cond(4) 00010110 Rd(4) 1111 Rm(4) 1010 Rn(4) ]", mnemonic="SMULTB")
@ispec("32[ .cond(4) 00010110 Rd(4) 1111 Rm(4) 1100 Rn(4) ]", mnemonic="SMULBT")
@ispec("32[ .cond(4) 00010110 Rd(4) 1111 Rm(4) 1110 Rn(4) ]", mnemonic="SMULTT")
@ispec("32[ .cond(4) 00010010 Rd(4) 0000 Rm(4) 1010 Rn(4) ]", mnemonic="SMULWB")
@ispec("32[ .cond(4) 00010010 Rd(4) 0000 Rm(4) 1110 Rn(4) ]", mnemonic="SMULWT")
@ispec("32[ .cond(4) 01111000 Rd(4) 1111 Rm(4) 0001 Rn(4) ]", mnemonic="USAD8")
def A_default(obj, Rd, Rm, Rn):
    obj.d = env.regs[Rd]
    obj.n = env.regs[Rn]
    obj.m = env.regs[Rm]
    obj.operands = [obj.d, obj.n, obj.m]
    if env.pc in obj.operands:
        raise InstructionError(obj)
    obj.type = type_data_processing


@ispec("32[ .cond(4) 0110101 sat_imm(5) Rd(4) imm5(5) sh 01 Rn(4) ]", mnemonic="SSAT")
@ispec("32[ .cond(4) 0110111 sat_imm(5) Rd(4) imm5(5) sh 01 Rn(4) ]", mnemonic="USAT")
def A_sreg(obj, sat_imm, Rd, imm5, sh, Rn):
    obj.d = env.regs[Rd]
    obj.n = DecodeShift(sh << 1, env.regs[Rn], env.cst(imm5, 5))
    obj.saturate_to = sat_imm + 1
    obj.operands = [obj.d, obj.saturate_to, obj.n]
    if env.pc in obj.operands:
        raise InstructionError(obj)
    obj.type = type_data_processing


@ispec("32[ .cond(4) 01101010 sat_imm(4) Rd(4) 1111 0001 Rn(4) ]", mnemonic="SSAT16")
@ispec("32[ .cond(4) 01101110 sat_imm(4) Rd(4) 1111 0011 Rn(4) ]", mnemonic="USAT16")
def A_default(obj, sat_imm, Rd, Rn):
    obj.d = env.regs[Rd]
    obj.n = env.regs[Rn]
    obj.saturate_to = sat_imm + 1
    obj.operands = [obj.d, obj.saturate_to, obj.n]
    if env.pc in obj.operands:
        raise InstructionError(obj)
    obj.type = type_data_processing


@ispec("32[ .cond(4) 1111 imm24(24) ]", mnemonic="SVC")
def A_default(obj, imm24):
    obj.imm32 = env.cst(imm24, 32)
    obj.operands = [obj.imm32]
    obj.type = type_control_flow


@ispec("32[ .cond(4) 00010 0 00 Rn(4) Rt(4) 0000 1001 Rt2(4) ]", mnemonic="SWP")
@ispec("32[ .cond(4) 00010 1 00 Rn(4) Rt(4) 0000 1001 Rt2(4) ]", mnemonic="SWPB")
def A_default(obj, Rn, Rt, Rt2):
    obj.n = env.regs[Rn]
    obj.t = env.regs[Rt]
    obj.t2 = env.regs[Rt2]
    obj.operands = [obj.t, obj.t2, obj.n]
    if env.pc in obj.operands:
        raise InstructionError(obj)
    if (Rn == Rt) or (Rn == Rt2):
        raise InstructionError(obj)
    obj.type = type_data_processing


@ispec(
    "32[ .cond(4) 01101000 Rn(4) Rd(4) rotate(2) 00 0111 Rm(4) ]", mnemonic="SXTAB16"
)
@ispec("32[ .cond(4) 01101010 Rn(4) Rd(4) rotate(2) 00 0111 Rm(4) ]", mnemonic="SXTAB")
@ispec("32[ .cond(4) 01101011 Rn(4) Rd(4) rotate(2) 00 0111 Rm(4) ]", mnemonic="SXTAH")
@ispec(
    "32[ .cond(4) 01101100 Rn(4) Rd(4) rotate(2) 00 0111 Rm(4) ]", mnemonic="UXTAB16"
)
@ispec("32[ .cond(4) 01101110 Rn(4) Rd(4) rotate(2) 00 0111 Rm(4) ]", mnemonic="UXTAB")
@ispec("32[ .cond(4) 01101111 Rn(4) Rd(4) rotate(2) 00 0111 Rm(4) ]", mnemonic="UXTAH")
def A_default(obj, Rn, Rd, rotate, Rm):
    obj.n = env.regs[Rn]
    obj.d = env.regs[Rd]
    obj.m = env.ror(env.regs[Rm], rotate * 8)
    obj.operands = [obj.d, obj.n, obj.m]
    if env.pc in obj.operands:
        raise InstructionError(obj)
    obj.type = type_data_processing


@ispec("32[ .cond(4) 01101000 1111 Rd(4) rotate(2) 00 0111 Rm(4) ]", mnemonic="SXTB16")
@ispec("32[ .cond(4) 01101010 1111 Rd(4) rotate(2) 00 0111 Rm(4) ]", mnemonic="SXTB")
@ispec("32[ .cond(4) 01101011 1111 Rd(4) rotate(2) 00 0111 Rm(4) ]", mnemonic="SXTH")
@ispec("32[ .cond(4) 01101100 1111 Rd(4) rotate(2) 00 0111 Rm(4) ]", mnemonic="UXTB16")
@ispec("32[ .cond(4) 01101110 1111 Rd(4) rotate(2) 00 0111 Rm(4) ]", mnemonic="UXTB")
@ispec("32[ .cond(4) 01101111 1111 Rd(4) rotate(2) 00 0111 Rm(4) ]", mnemonic="UXTH")
def A_default(obj, Rd, rotate, Rm):
    obj.d = env.regs[Rd]
    obj.m = env.ror(env.regs[Rm], rotate * 8)
    obj.operands = [obj.d, obj.m]
    if env.pc in obj.operands:
        raise InstructionError(obj)
    obj.type = type_data_processing


@ispec(
    "32[ .cond(4) 1110 cpop1(3) 0 Cd(4) src(4) cpnum(4) cpop2(3) 1 cpreg(4) ]",
    mnemonic="MCR",
)
@ispec(
    "32[ 1111     1110 cpop1(3) 0 Cd(4) src(4) cpnum(4) cpop2(3) 1 cpreg(4) ]",
    mnemonic="MCR2",
)
def A_cp(obj, cpop1, Cd, src, cpnum, cpop2, cpreg):
    obj.p = env.cpname[cpnum]
    obj.s = env.regs[src]
    obj.d = env.cpregs[obj.p][Cd]
    obj.a = env.cpregs[obj.p][cpreg]
    obj.operands = [obj.p, cpop1, obj.s, obj.d, obj.a, cpop2]
    obj.type = type_system


@ispec(
    "32[ .cond(4) 1110 cpop1(3) 1 Cs(4) dst(4) cpnum(4) cpop2(3) 1 cpreg(4) ]",
    mnemonic="MRC",
)
@ispec(
    "32[ 1111     1110 cpop1(3) 1 Cs(4) dst(4) cpnum(4) cpop2(3) 1 cpreg(4) ]",
    mnemonic="MRC2",
)
def A_cp(obj, cpop1, Cs, dst, cpnum, cpop2, cpreg):
    obj.p = env.cpname[cpnum]
    obj.d = env.regs[dst]
    obj.s = env.cpregs[obj.p][Cs]
    obj.a = env.cpregs[obj.p][cpreg]
    obj.operands = [obj.p, cpop1, obj.d, obj.s, obj.a, cpop2]
    obj.type = type_system
