# instructions

platform: ARM
mnem: ADC
description:
Add with carry: Rd = Rn + Rm + C       (C6.6.1)




    31 30 29 28 27 26 25 24 23 22 21 20            16 15 14 13 12 11 10 9             5 4              0
    sf 0 0 1 1 0 1 0 0 0 0                  Rm         0 0 0 0 0 0              Rn              Rd
       op S


32-bit variant

Applies when sf = 0.

ADC <Wd>, <Wn>, <Wm>


64-bit variant

Applies when sf = 1.

ADC <Xd>, <Xn>, <Xm>


Decode for all variants of this encoding

  integer d = UInt(Rd);
  integer n = UInt(Rn);
  integer m = UInt(Rm);
  integer datasize = if sf == '1' then 64 else 32;
  boolean sub_op = (op == '1');
  boolean setflags = (S == '1');


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Wm>            Is the 32-bit name of the second general-purpose source register, encoded in the "Rm" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Xm>            Is the 64-bit name of the second general-purpose source register, encoded in the "Rm" field.


Operation

  bits(datasize) result;
  bits(datasize) operand1 = X[n];
  bits(datasize) operand2 = X[m];
  bits(4) nzcv;

  if sub_op then
       operand2 = NOT(operand2);

  (result, nzcv) = AddWithCarry(operand1, operand2, PSTATE.C);

  if setflags then
       PSTATE.<N,Z,C,V> = nzcv;

  X[d] = result;


platform: ARM
mnem: ADCS
description:
Add with carry, setting the condition flags: Rd = Rn + Rm + C       (C6.6.2)




  31 30 29 28 27 26 25 24 23 22 21 20             16 15 14 13 12 11 10 9              5 4              0
  sf 0 1 1 1 0 1 0 0 0 0                   Rm         0 0 0 0 0 0              Rn              Rd
     op S


32-bit variant

Applies when sf = 0.

ADCS <Wd>, <Wn>, <Wm>


64-bit variant

Applies when sf = 1.

ADCS <Xd>, <Xn>, <Xm>


Decode for all variants of this encoding

 integer d = UInt(Rd);
 integer n = UInt(Rn);
 integer m = UInt(Rm);
 integer datasize = if sf == '1' then 64 else 32;
 boolean sub_op = (op == '1');
 boolean setflags = (S == '1');


Assembler symbols

<Wd>           Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>           Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Wm>           Is the 32-bit name of the second general-purpose source register, encoded in the "Rm" field.

<Xd>           Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>           Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Xm>           Is the 64-bit name of the second general-purpose source register, encoded in the "Rm" field.


Operation

 bits(datasize) result;
 bits(datasize) operand1 = X[n];
 bits(datasize) operand2 = X[m];
 bits(4) nzcv;

 if sub_op then
     operand2 = NOT(operand2);

 (result, nzcv) = AddWithCarry(operand1, operand2, PSTATE.C);

 if setflags then
     PSTATE.<N,Z,C,V> = nzcv;

 X[d] = result;


platform: ARM
mnem: ADD
description:
       Add (extended register): Rd = Rn + LSL(extend(Rm), amount)       (C6.6.3)




           31 30 29 28 27 26 25 24 23 22 21 20            16 15     13 12      10 9            5 4            0
           sf 0 0 0 1 0 1 1 0 0 1                  Rm          option    imm3           Rn              Rd
              op S


       32-bit variant

       Applies when sf = 0.

       ADD <Wd|WSP>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}


       64-bit variant

       Applies when sf = 1.

       ADD <Xd|SP>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}


       Decode for all variants of this encoding

         integer d = UInt(Rd);
         integer n = UInt(Rn);
         integer m = UInt(Rm);
         integer datasize = if sf == '1' then 64 else 32;
         boolean sub_op = (op == '1');
         boolean setflags = (S == '1');
         ExtendType extend_type = DecodeRegExtend(option);
         integer shift = UInt(imm3);
         if shift > 4 then ReservedValue();


       Assembler symbols

       <Wd|WSP>        Is the 32-bit name of the destination general-purpose register or stack pointer, encoded in the "Rd"
                       field.

       <Wn|WSP>        Is the 32-bit name of the first source general-purpose register or stack pointer, encoded in the "Rn"
                       field.

       <Wm>            Is the 32-bit name of the second general-purpose source register, encoded in the "Rm" field.

       <Xd|SP>         Is the 64-bit name of the destination general-purpose register or stack pointer, encoded in the "Rd"
                       field.

       <Xn|SP>         Is the 64-bit name of the first source general-purpose register or stack pointer, encoded in the "Rn"
                       field.

       <R>             Is a width specifier, encoded in the "option" field. It can have the following values:

                       W           when option = 00x

                       W           when option = 010

                       X           when option = x11

                       W           when option = 10x

                       W           when option = 110

       <m>             Is the number [0-30] of the second general-purpose source register or the name ZR (31), encoded in
                       the "Rm" field.
<extend>      For the 32-bit variant: is the extension to be applied to the second source operand, encoded in the
              "option" field. It can have the following values:

              UXTB         when option = 000

              UXTH         when option = 001

              LSL|UXTW     when option = 010

              UXTX         when option = 011

              SXTB         when option = 100

              SXTH         when option = 101

              SXTW         when option = 110

              SXTX         when option = 111

              If "Rd" or "Rn" is '11111' (WSP) and "option" is '010' then LSL is preferred, but may be omitted
              when "imm3" is '000'. In all other cases <extend> is required and must be UXTW when "option" is
              '010'.

              For the 64-bit variant: is the extension to be applied to the second source operand, encoded in the
              "option" field. It can have the following values:

              UXTB         when option = 000

              UXTH         when option = 001

              UXTW         when option = 010

              LSL|UXTX     when option = 011

              SXTB         when option = 100

              SXTH         when option = 101

              SXTW         when option = 110

              SXTX         when option = 111

              If "Rd" or "Rn" is '11111' (SP) and "option" is '011' then LSL is preferred, but may be omitted when
              "imm3" is '000'. In all other cases <extend> is required and must be UXTX when "option" is '011'.

<amount>      Is the left shift amount to be applied after extension in the range 0 to 4, defaulting to 0, encoded in
              the "imm3" field. It must be absent when <extend> is absent, is required when <extend> is LSL,
              and is optional when <extend> is present but not LSL.


Operation

 bits(datasize) result;
 bits(datasize) operand1 = if n == 31 then SP[] else X[n];
 bits(datasize) operand2 = ExtendReg(m, extend_type, shift);
 bits(4) nzcv;
 bit carry_in;

 if sub_op then
     operand2 = NOT(operand2);
     carry_in = '1';
 else
     carry_in = '0';

 (result, nzcv) = AddWithCarry(operand1, operand2, carry_in);

 if setflags then
     PSTATE.<N,Z,C,V> = nzcv;

 if d == 31 && !setflags then
     SP[] = result;
 else
     X[d] = result;


platform: ARM
mnem: ADDS
description:
       Add (extended register), setting the condition flags: Rd = Rn + LSL(extend(Rm), amount)       (C6.6.6)

       This instruction is used by the alias CMN (extended register). See the Alias conditions table for details of when each
       alias is preferred.




           31 30 29 28 27 26 25 24 23 22 21 20             16 15     13 12      10 9            5 4             0
           sf 0 1 0 1 0 1 1 0 0 1                   Rm          option    imm3           Rn              Rd
              op S


       32-bit variant

       Applies when sf = 0.

       ADDS <Wd>, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}


       64-bit variant

       Applies when sf = 1.

       ADDS <Xd>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}


       Decode for all variants of this encoding

         integer d = UInt(Rd);
         integer n = UInt(Rn);
         integer m = UInt(Rm);
         integer datasize = if sf == '1' then 64 else 32;
         boolean sub_op = (op == '1');
         boolean setflags = (S == '1');
         ExtendType extend_type = DecodeRegExtend(option);
         integer shift = UInt(imm3);
         if shift > 4 then ReservedValue();


       Alias conditions


                             Alias                     is preferred when

                             CMN (extended             Rd == '11111'
                             register)


       Assembler symbols

       <Wd>             Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <Wn|WSP>         Is the 32-bit name of the first source general-purpose register or stack pointer, encoded in the "Rn"
                        field.

       <Wm>             Is the 32-bit name of the second general-purpose source register, encoded in the "Rm" field.

       <Xd>             Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <Xn|SP>          Is the 64-bit name of the first source general-purpose register or stack pointer, encoded in the "Rn"
                        field.

       <R>              Is a width specifier, encoded in the "option" field. It can have the following values:

                        W           when option = 00x
              W            when option = 010

              X            when option = x11

              W            when option = 10x

              W            when option = 110

<m>           Is the number [0-30] of the second general-purpose source register or the name ZR (31), encoded in
              the "Rm" field.

<extend>      For the 32-bit variant: is the extension to be applied to the second source operand, encoded in the
              "option" field. It can have the following values:

              UXTB         when option = 000

              UXTH         when option = 001

              LSL|UXTW     when option = 010

              UXTX         when option = 011

              SXTB         when option = 100

              SXTH         when option = 101

              SXTW         when option = 110

              SXTX         when option = 111

              If "Rn" is '11111' (WSP) and "option" is '010' then LSL is preferred, but may be omitted when
              "imm3" is '000'. In all other cases <extend> is required and must be UXTW when "option" is '010'.

              For the 64-bit variant: is the extension to be applied to the second source operand, encoded in the
              "option" field. It can have the following values:

              UXTB         when option = 000

              UXTH         when option = 001

              UXTW         when option = 010

              LSL|UXTX     when option = 011

              SXTB         when option = 100

              SXTH         when option = 101

              SXTW         when option = 110

              SXTX         when option = 111

              If "Rn" is '11111' (SP) and "option" is '011' then LSL is preferred, but may be omitted when "imm3"
              is '000'. In all other cases <extend> is required and must be UXTX when "option" is '011'.

<amount>      Is the left shift amount to be applied after extension in the range 0 to 4, defaulting to 0, encoded in
              the "imm3" field. It must be absent when <extend> is absent, is required when <extend> is LSL,
              and is optional when <extend> is present but not LSL.


Operation

 bits(datasize) result;
 bits(datasize) operand1 = if n == 31 then SP[] else X[n];
 bits(datasize) operand2 = ExtendReg(m, extend_type, shift);
 bits(4) nzcv;
 bit carry_in;

 if sub_op then
     operand2 = NOT(operand2);
     carry_in = '1';
 else
     carry_in = '0';

 (result, nzcv) = AddWithCarry(operand1, operand2, carry_in);

 if setflags then
              PSTATE.<N,Z,C,V> = nzcv;

         if d == 31 && !setflags then
              SP[] = result;
         else
              X[d] = result;


platform: ARM
mnem: ADR
description:
Address of label at a PC-relative offset       (C6.6.9)




  31 30 29 28 27 26 25 24 23                                                           5 4              0
  0 immlo 1 0 0 0 0                                   immhi                                     Rd
  op


Literal variant

ADR <Xd>, <label>


Decode for this encoding

 integer d = UInt(Rd);
 boolean page = (op == '1');
 bits(64) imm;

 if page then
     imm = SignExtend(immhi:immlo:Zeros(12), 64);
 else
     imm = SignExtend(immhi:immlo, 64);


Assembler symbols

<Xd>           Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<label>        Is the program label whose address is to be calculated. Its offset from the address of this instruction,
               in the range +/-1MB, is encoded in "immhi:immlo".


Operation

 bits(64) base = PC[];

 if page then
     base<11:0> = Zeros(12);

 X[d] = base + imm;


platform: ARM
mnem: ADRP
description:
Address of 4KB page at a PC-relative offset       (C6.6.10)




    31 30 29 28 27 26 25 24 23                                                        5 4             0
    1 immlo 1 0 0 0 0                                   immhi                                  Rd
    op


Literal variant

ADRP <Xd>, <label>


Decode for this encoding

  integer d = UInt(Rd);
  boolean page = (op == '1');
  bits(64) imm;

  if page then
       imm = SignExtend(immhi:immlo:Zeros(12), 64);
  else
       imm = SignExtend(immhi:immlo, 64);


Assembler symbols

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<label>         Is the program label whose 4KB page address is to be calculated. Its offset from the page address of
                this instruction, in the range +/-4GB, is encoded as "immhi:immlo" times 4096.


Operation

  bits(64) base = PC[];

  if page then
       base<11:0> = Zeros(12);

  X[d] = base + imm;


platform: ARM
mnem: AND
description:
Bitwise AND (immediate): Rd = Rn AND imm       (C6.6.11)




  31 30 29 28 27 26 25 24 23 22 21               16 15             10 9             5 4              0
  sf 0 0 1 0 0 1 0 0 N                 immr               imms               Rn               Rd
     opc


32-bit variant

Applies when sf = 0 && N = 0.

AND <Wd|WSP>, <Wn>, #<imm>


64-bit variant

Applies when sf = 1.

AND <Xd|SP>, <Xn>, #<imm>


Decode for all variants of this encoding

 integer d = UInt(Rd);
 integer n = UInt(Rn);
 integer datasize = if sf == '1' then 64 else 32;
 boolean setflags;
 LogicalOp op;
 case opc of
     when '00' op = LogicalOp_AND; setflags = FALSE;
     when '01' op = LogicalOp_ORR; setflags = FALSE;
     when '10' op = LogicalOp_EOR; setflags = FALSE;
     when '11' op = LogicalOp_AND; setflags = TRUE;

 bits(datasize) imm;
 if sf == '0' && N != '0' then ReservedValue();
 (imm, -) = DecodeBitMasks(N, imms, immr, TRUE);


Assembler symbols

<Wd|WSP>      Is the 32-bit name of the destination general-purpose register or stack pointer, encoded in the "Rd"
              field.

<Wn>          Is the 32-bit name of the general-purpose source register, encoded in the "Rn" field.

<Xd|SP>       Is the 64-bit name of the destination general-purpose register or stack pointer, encoded in the "Rd"
              field.

<Xn>          Is the 64-bit name of the general-purpose source register, encoded in the "Rn" field.

<imm>         Is the bitmask immediate, encoded in "N:imms:immr".


Operation

 bits(datasize) result;
 bits(datasize) operand1 = X[n];
 bits(datasize) operand2 = imm;

 case op of
     when LogicalOp_AND result = operand1 AND operand2;
     when LogicalOp_ORR result = operand1 OR     operand2;
     when LogicalOp_EOR result = operand1 EOR operand2;

         if setflags then
              PSTATE.<N,Z,C,V> = result<datasize-1>:IsZeroBit(result):'00';

         if d == 31 && !setflags then
              SP[] = result;
         else
              X[d] = result;


platform: ARM
mnem: ANDS
description:
Bitwise AND (immediate), setting the condition flags: Rd = Rn AND imm       (C6.6.13)

This instruction is used by the alias TST (immediate). See the Alias conditions table for details of when each alias
is preferred.




  31 30 29 28 27 26 25 24 23 22 21                16 15              10 9             5 4              0
   sf 1 1 1 0 0 1 0 0 N                  immr              imms                Rn              Rd
       opc


32-bit variant

Applies when sf = 0 && N = 0.

ANDS <Wd>, <Wn>, #<imm>


64-bit variant

Applies when sf = 1.

ANDS <Xd>, <Xn>, #<imm>


Decode for all variants of this encoding

 integer d = UInt(Rd);
 integer n = UInt(Rn);
 integer datasize = if sf == '1' then 64 else 32;
 boolean setflags;
 LogicalOp op;
 case opc of
     when '00' op = LogicalOp_AND; setflags = FALSE;
     when '01' op = LogicalOp_ORR; setflags = FALSE;
     when '10' op = LogicalOp_EOR; setflags = FALSE;
     when '11' op = LogicalOp_AND; setflags = TRUE;

 bits(datasize) imm;
 if sf == '0' && N != '0' then ReservedValue();
 (imm, -) = DecodeBitMasks(N, imms, immr, TRUE);


Alias conditions


                     Alias                   is preferred when

                     TST (immediate)         Rd == '11111'



Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the general-purpose source register, encoded in the "Rn" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the general-purpose source register, encoded in the "Rn" field.

<imm>           Is the bitmask immediate, encoded in "N:imms:immr".
       Operation

         bits(datasize) result;
         bits(datasize) operand1 = X[n];
         bits(datasize) operand2 = imm;

         case op of
              when LogicalOp_AND result = operand1 AND operand2;
              when LogicalOp_ORR result = operand1 OR  operand2;
              when LogicalOp_EOR result = operand1 EOR operand2;

         if setflags then
              PSTATE.<N,Z,C,V> = result<datasize-1>:IsZeroBit(result):'00';

         if d == 31 && !setflags then
              SP[] = result;
         else
              X[d] = result;


platform: ARM
mnem: ASR
description:
Arithmetic shift right (register): Rd = ASR(Rn, Rm)       (C6.6.15)

This instruction is an alias of the ASRV instruction. This means that:

.      The encodings in this description are named to match the encodings of ASRV.

.      The description of ASRV gives the operational pseudocode for this instruction.




  31 30 29 28 27 26 25 24 23 22 21 20              16 15 14 13 12 11 10 9              5 4              0
   sf 0 0 1 1 0 1 0 1 1 0                   Rm         0 0 1 0 1 0              Rn              Rd
                                                                   op2


32-bit variant

Applies when sf = 0.

ASR <Wd>, <Wn>, <Wm>

is equivalent to

ASRV <Wd>, <Wn>, <Wm>

and is always the preferred disassembly.

64-bit variant

Applies when sf = 1.

ASR <Xd>, <Xn>, <Xm>

is equivalent to

ASRV <Xd>, <Xn>, <Xm>

and is always the preferred disassembly.


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Wm>            Is the 32-bit name of the second general-purpose source register holding a shift amount from 0 to
                31 in its bottom 5 bits, encoded in the "Rm" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Xm>            Is the 64-bit name of the second general-purpose source register holding a shift amount from 0 to
                63 in its bottom 6 bits, encoded in the "Rm" field.


Operation

The description of ASRV gives the operational pseudocode for this instruction.


platform: ARM
mnem: ASRV
description:
Arithmetic shift right variable : Rd = ASR(Rn, Rm)       (C6.6.17)

This instruction is used by the alias ASR (register). The alias is always the preferred disassembly.




  31 30 29 28 27 26 25 24 23 22 21 20              16 15 14 13 12 11 10 9              5 4              0
  sf 0 0 1 1 0 1 0 1 1 0                    Rm         0 0 1 0 1 0              Rn              Rd
                                                                     op2


32-bit variant

Applies when sf = 0.

ASRV <Wd>, <Wn>, <Wm>


64-bit variant

Applies when sf = 1.

ASRV <Xd>, <Xn>, <Xm>


Decode for all variants of this encoding

 integer d = UInt(Rd);
 integer n = UInt(Rn);
 integer m = UInt(Rm);
 integer datasize = if sf == '1' then 64 else 32;
 ShiftType shift_type = DecodeShift(op2);


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Wm>            Is the 32-bit name of the second general-purpose source register holding a shift amount from 0 to
                31 in its bottom 5 bits, encoded in the "Rm" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Xm>            Is the 64-bit name of the second general-purpose source register holding a shift amount from 0 to
                63 in its bottom 6 bits, encoded in the "Rm" field.


Operation

 bits(datasize) result;
 bits(datasize) operand2 = X[m];

 result = ShiftReg(n, shift_type, UInt(operand2) MOD datasize);
 X[d] = result;


platform: ARM
mnem: AT
description:
Address translate       (C6.6.18)

This instruction is an alias of the SYS instruction. This means that:

.       The encodings in this description are named to match the encodings of SYS.

.       The description of SYS gives the operational pseudocode for this instruction.




    31 30 29 28 27 26 25 24 23 22 21 20 19 18      16 15       12 11        8 7      5 4             0
    1 1 0 1 0 1 0 1 0 0 0 0 1                  op1     0 1 1 1 1 0 0 0           op2           Rt
                                    L                     CRn         CRm


System variant

AT <at_op>, <Xt>

is equivalent to

SYS #<op1>, C7, C8, #<op2>, <Xt>

and is the preferred disassembly when SysOp(op1,'0111','1000',op2) == Sys_AT.


Assembler symbols

<at_op>         Is an AT operation name, as listed for the AT system operation group, encoded in the "op1:op2"
                field. It can have the following values:

                S1E1R        when op1 = 000, op2 = 000

                S1E1W        when op1 = 000, op2 = 001

                S1E0R        when op1 = 000, op2 = 010

                S1E0W        when op1 = 000, op2 = 011

                S1E2R        when op1 = 100, op2 = 000

                S1E2W        when op1 = 100, op2 = 001

                S12E1R       when op1 = 100, op2 = 100

                S12E1W       when op1 = 100, op2 = 101

                S12E0R       when op1 = 100, op2 = 110

                S12E0W       when op1 = 100, op2 = 111

                S1E3R        when op1 = 110, op2 = 000

                S1E3W        when op1 = 110, op2 = 001

<op1>           Is a 3-bit unsigned immediate, in the range 0 to 7, encoded in the "op1" field.

<op2>           Is a 3-bit unsigned immediate, in the range 0 to 7, encoded in the "op2" field.

<Xt>            Is the 64-bit name of the general-purpose source register, encoded in the "Rt" field.


Operation

The description of SYS gives the operational pseudocode for this instruction.


platform: ARM
mnem: B.cond
description:
Branch conditionally to a label at a PC-relative offset, with a hint that this is not a subroutine call or return.       (C6.6.19)




  31 30 29 28 27 26 25 24 23                                                              5 4 3            0
  0 1 0 1 0 1 0 0                                      imm19                                 0     cond




19-bit signed PC-relative branch offset variant

B.<cond> <label>


Decode for this encoding

 bits(64) offset = SignExtend(imm19:'00', 64);
 bits(4) condition = cond;


Assembler symbols

<cond>        Is one of the standard conditions, encoded in the "cond" field in the standard way.

<label>       Is the program label to be conditionally branched to. Its offset from the address of this instruction,
              in the range +/-1MB, is encoded as "imm19" times 4.


Operation

 if ConditionHolds(condition) then
     BranchTo(PC[] + offset, BranchType_JMP);


platform: ARM
mnem: B
description:
Branch causes an unconditional branch to a label at a PC-relative offset, with a hint that this is not a subroutine call       (C6.6.20)
or return.




    31 30 29 28 27 26 25                                                                                  0
    0 0 0 1 0 1                                            imm26
    op


26-bit signed PC-relative branch offset variant

B <label>


Decode for this encoding

  BranchType branch_type = if op == '1' then BranchType_CALL else BranchType_JMP;
  bits(64) offset = SignExtend(imm26:'00', 64);


Assembler symbols

<label>         Is the program label to be unconditionally branched to. Its offset from the address of this instruction,
                in the range +/-128MB, is encoded as "imm26" times 4.


Operation

  if branch_type == BranchType_CALL then X[30] = PC[] + 4;

  BranchTo(PC[] + offset, branch_type);


platform: ARM
mnem: BFI
description:
Bitfield insert, leaving other bits unchanged       (C6.6.21)

This instruction is an alias of the BFM instruction. This means that:

.      The encodings in this description are named to match the encodings of BFM.

.      The description of BFM gives the operational pseudocode for this instruction.




  31 30 29 28 27 26 25 24 23 22 21                    16 15                10 9            5 4               0
   sf 0 1 1 0 0 1 1 0 N                     immr                imms                Rn               Rd
      opc


32-bit variant

Applies when sf = 0 && N = 0.

BFI <Wd>, <Wn>, #<lsb>, #<width>

is equivalent to

BFM  <Wd>, <Wn>, #(-<lsb> MOD 32), #(<width>-1)

and is the preferred disassembly when UInt(imms) < UInt(immr).

64-bit variant

Applies when sf = 1 && N = 1.

BFI <Xd>, <Xn>, #<lsb>, #<width>

is equivalent to

BFM  <Xd>, <Xn>, #(-<lsb> MOD 64), #(<width>-1)

and is the preferred disassembly when UInt(imms) < UInt(immr).


Assembler symbols

<Wd>              Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>              Is the 32-bit name of the general-purpose source register, encoded in the "Rn" field.

<Xd>              Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>              Is the 64-bit name of the general-purpose source register, encoded in the "Rn" field.

<lsb>             For the 32-bit variant: is the bit number of the lsb of the destination bitfield, in the range 0 to 31.

                  For the 64-bit variant: is the bit number of the lsb of the destination bitfield, in the range 0 to 63.

<width>           For the 32-bit variant: is the width of the bitfield, in the range 1 to 32-<lsb>.

                  For the 64-bit variant: is the width of the bitfield, in the range 1 to 64-<lsb>.


Operation

The description of BFM gives the operational pseudocode for this instruction.


platform: ARM
mnem: BFM
description:
       Bitfield move, leaving other bits unchanged       (C6.6.22)

       This instruction is used by the aliases BFI and BFXIL. See the Alias conditions on page C6-433 table for details of
       when each alias is preferred.




           31 30 29 28 27 26 25 24 23 22 21              16 15              10 9            5 4            0
           sf 0 1 1 0 0 1 1 0 N                 immr               imms              Rn            Rd
               opc


       32-bit variant

       Applies when sf = 0 && N = 0.

       BFM <Wd>, <Wn>, #<immr>, #<imms>


       64-bit variant

       Applies when sf = 1 && N = 1.

       BFM <Xd>, <Xn>, #<immr>, #<imms>


       Decode for all variants of this encoding

         integer d = UInt(Rd);
         integer n = UInt(Rn);
         integer datasize = if sf == '1' then 64 else 32;

         boolean inzero;
         boolean extend;
         integer R;
         integer S;
         bits(datasize) wmask;
         bits(datasize) tmask;

         case opc of
              when '00' inzero = TRUE;    extend = TRUE;      // SBFM
              when '01' inzero = FALSE; extend = FALSE;       // BFM
              when '10' inzero = TRUE;    extend = FALSE;     // UBFM
              when '11' UnallocatedEncoding();

         if sf == '1' && N != '1' then ReservedValue();
         if sf == '0' && (N != '0' || immr<5> != '0' || imms<5> != '0') then ReservedValue();

         R = UInt(immr);
         S = UInt(imms);
         (wmask, tmask) = DecodeBitMasks(N, imms, immr, FALSE);
Alias conditions


                   Alias                      is preferred when

                   BFI                        UInt(imms) < UInt(immr)

                   BFXIL                      UInt(imms) >= UInt(immr)



Assembler symbols

<Wd>          Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>          Is the 32-bit name of the general-purpose source register, encoded in the "Rn" field.

<Xd>          Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>          Is the 64-bit name of the general-purpose source register, encoded in the "Rn" field.

<immr>        For the 32-bit variant: is the right rotate amount, in the range 0 to 31, encoded in the "immr" field.

              For the 64-bit variant: is the right rotate amount, in the range 0 to 63, encoded in the "immr" field.

<imms>        For the 32-bit variant: is the leftmost bit number to be moved from the source, in the range 0 to 31,
              encoded in the "imms" field.

              For the 64-bit variant: is the leftmost bit number to be moved from the source, in the range 0 to 63,
              encoded in the "imms" field.


Operation

 bits(datasize) dst = if inzero then Zeros() else X[d];
 bits(datasize) src = X[n];

 // perform bitfield move on low bits
 bits(datasize) bot = (dst AND NOT(wmask)) OR (ROR(src, R) AND wmask);

 // determine extension bits (sign, zero or dest register)
 bits(datasize) top = if extend then Replicate(src<S>) else dst;

 // combine extension bits and result bits
 X[d] = (top AND NOT(tmask)) OR (bot AND tmask);


platform: ARM
mnem: BFXIL
description:
Bitfield extract and insert at low end, leaving other bits unchanged       (C6.6.23)

This instruction is an alias of the BFM instruction. This means that:

.       The encodings in this description are named to match the encodings of BFM.

.       The description of BFM gives the operational pseudocode for this instruction.




    31 30 29 28 27 26 25 24 23 22 21                 16 15                10 9            5 4              0
    sf 0 1 1 0 0 1 1 0 N                   immr                imms                Rn              Rd
        opc


32-bit variant

Applies when sf = 0 && N = 0.

BFXIL <Wd>, <Wn>, #<lsb>, #<width>

is equivalent to

BFM    <Wd>, <Wn>, #<lsb>, #(<lsb>+<width>-1)

and is the preferred disassembly when UInt(imms) >= UInt(immr).

64-bit variant

Applies when sf = 1 && N = 1.

BFXIL <Xd>, <Xn>, #<lsb>, #<width>

is equivalent to

BFM    <Xd>, <Xn>, #<lsb>, #(<lsb>+<width>-1)

and is the preferred disassembly when UInt(imms) >= UInt(immr).


Assembler symbols

<Wd>             Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>             Is the 32-bit name of the general-purpose source register, encoded in the "Rn" field.

<Xd>             Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>             Is the 64-bit name of the general-purpose source register, encoded in the "Rn" field.

<lsb>            For the 32-bit variant: is the bit number of the lsb of the source bitfield, in the range 0 to 31.

                 For the 64-bit variant: is the bit number of the lsb of the source bitfield, in the range 0 to 63.

<width>          For the 32-bit variant: is the width of the bitfield, in the range 1 to 32-<lsb>.

                 For the 64-bit variant: is the width of the bitfield, in the range 1 to 64-<lsb>.


Operation

The description of BFM gives the operational pseudocode for this instruction.


platform: ARM
mnem: BIC
description:
Bitwise bit clear (shifted register): Rd = Rn AND NOT shift(Rm, amount)       (C6.6.24)




  31 30 29 28 27 26 25 24 23 22 21 20               16 15               10 9             5 4             0
  sf 0 0 0 1 0 1 0 shift 1                   Rm               imm6                Rn            Rd
     opc                            N


32-bit variant

Applies when sf = 0.

BIC <Wd>, <Wn>, <Wm>{, <shift> #<amount>}


64-bit variant

Applies when sf = 1.

BIC <Xd>, <Xn>, <Xm>{, <shift> #<amount>}


Decode for all variants of this encoding

integer d = UInt(Rd);
integer n = UInt(Rn);
integer m = UInt(Rm);
integer datasize = if sf == '1' then 64 else 32;
boolean setflags;
 LogicalOp op;
case opc of
     when '00' op = LogicalOp_AND; setflags = FALSE;
     when '01' op = LogicalOp_ORR; setflags = FALSE;
     when '10' op = LogicalOp_EOR; setflags = FALSE;
     when '11' op = LogicalOp_AND; setflags = TRUE;

if sf == '0' && imm6<5> == '1' then ReservedValue();

 ShiftType shift_type = DecodeShift(shift);
integer shift_amount = UInt(imm6);
boolean invert = (N == '1');


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Wm>            Is the 32-bit name of the second general-purpose source register, encoded in the "Rm" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Xm>            Is the 64-bit name of the second general-purpose source register, encoded in the "Rm" field.

<shift>         Is the optional shift to be applied to the final source, defaulting to LSL and encoded in the "shift"
                field. It can have the following values:

                LSL          when shift = 00

                LSR          when shift = 01

                ASR          when shift = 10

                ROR          when shift = 11
      <amount>        For the 32-bit variant: is the shift amount, in the range 0 to 31, defaulting to 0 and encoded in the
                      "imm6" field.

                      For the 64-bit variant: is the shift amount, in the range 0 to 63, defaulting to 0 and encoded in the
                      "imm6" field.


      Operation

        bits(datasize) operand1 = X[n];
        bits(datasize) operand2 = ShiftReg(m, shift_type, shift_amount);

        if invert then operand2 = NOT(operand2);

        case op of
             when LogicalOp_AND result = operand1 AND operand2;
             when LogicalOp_ORR result = operand1 OR       operand2;
             when LogicalOp_EOR result = operand1 EOR operand2;

        if setflags then
             PSTATE.<N,Z,C,V> = result<datasize-1>:IsZeroBit(result):'00';

        X[d] = result;


platform: ARM
mnem: BICS
description:
Bitwise bit clear (shifted register), setting the condition flags: Rd = Rn AND NOT shift(Rm, amount)       (C6.6.25)




  31 30 29 28 27 26 25 24 23 22 21 20                16 15              10 9             5 4             0
  sf 1 1 0 1 0 1 0 shift 1                    Rm               imm6               Rn            Rd
     opc                            N


32-bit variant

Applies when sf = 0.

BICS <Wd>, <Wn>, <Wm>{, <shift> #<amount>}


64-bit variant

Applies when sf = 1.

BICS <Xd>, <Xn>, <Xm>{, <shift> #<amount>}


Decode for all variants of this encoding

 integer d = UInt(Rd);
 integer n = UInt(Rn);
 integer m = UInt(Rm);
 integer datasize = if sf == '1' then 64 else 32;
 boolean setflags;
 LogicalOp op;
 case opc of
     when '00' op = LogicalOp_AND; setflags = FALSE;
     when '01' op = LogicalOp_ORR; setflags = FALSE;
     when '10' op = LogicalOp_EOR; setflags = FALSE;
     when '11' op = LogicalOp_AND; setflags = TRUE;

 if sf == '0' && imm6<5> == '1' then ReservedValue();

 ShiftType shift_type = DecodeShift(shift);
 integer shift_amount = UInt(imm6);
 boolean invert = (N == '1');


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Wm>            Is the 32-bit name of the second general-purpose source register, encoded in the "Rm" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Xm>            Is the 64-bit name of the second general-purpose source register, encoded in the "Rm" field.

<shift>         Is the optional shift to be applied to the final source, defaulting to LSL and encoded in the "shift"
                field. It can have the following values:

                LSL          when shift = 00

                LSR          when shift = 01

                ASR          when shift = 10

                ROR          when shift = 11
       <amount>        For the 32-bit variant: is the shift amount, in the range 0 to 31, defaulting to 0 and encoded in the
                       "imm6" field.

                       For the 64-bit variant: is the shift amount, in the range 0 to 63, defaulting to 0 and encoded in the
                       "imm6" field.


       Operation

         bits(datasize) operand1 = X[n];
         bits(datasize) operand2 = ShiftReg(m, shift_type, shift_amount);

         if invert then operand2 = NOT(operand2);

         case op of
              when LogicalOp_AND result = operand1 AND operand2;
              when LogicalOp_ORR result = operand1 OR       operand2;
              when LogicalOp_EOR result = operand1 EOR operand2;

         if setflags then
              PSTATE.<N,Z,C,V> = result<datasize-1>:IsZeroBit(result):'00';

         X[d] = result;


platform: ARM
mnem: BL
description:
Branch with Link calls a subroutine at a PC-relative offset, setting the register X30 to PC+4. It provides a hint that       (C6.6.26)
this is not a subroutine call or return.




  31 30 29 28 27 26 25                                                                                    0
   1 0 0 1 0 1                                              imm26
  op


26-bit signed PC-relative branch offset variant

BL <label>


Decode for this encoding

 BranchType branch_type = if op == '1' then BranchType_CALL else BranchType_JMP;
 bits(64) offset = SignExtend(imm26:'00', 64);


Assembler symbols

<label>          Is the program label to be unconditionally branched to. Its offset from the address of this instruction,
                 in the range +/-128MB, is encoded as "imm26" times 4.


Operation

 if branch_type == BranchType_CALL then X[30] = PC[] + 4;

 BranchTo(PC[] + offset, branch_type);


platform: ARM
mnem: BLR
description:
Branch with Link to Register calls a subroutine at an address in a register, setting register X30 to PC+4.       (C6.6.27)




    31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9                5 4 3 2 1 0
    1 1 0 1 0 1 1 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0                                 Rn         0 0 0 0 0
                                op


Integer variant

BLR <Xn>


Decode for this encoding

  integer n = UInt(Rn);
  BranchType branch_type;

  case op of
       when '00' branch_type = BranchType_JMP;
       when '01' branch_type = BranchType_CALL;
       when '10' branch_type = BranchType_RET;
       otherwise UnallocatedEncoding();


Assembler symbols

<Xn>            Is the 64-bit name of the general-purpose register holding the address to be branched to, encoded in
                the "Rn" field.


Operation

  bits(64) target = X[n];

  if branch_type == BranchType_CALL then X[30] = PC[] + 4;
  BranchTo(target, branch_type);


platform: ARM
mnem: BR
description:
Branch to Register branches unconditionally to an address in a register, with a hint that this is not a subroutine return.       (C6.6.28)




  31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9                    5 4 3 2 1 0
  1 1 0 1 0 1 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0                                   Rn           0 0 0 0 0
                               op


Integer variant

BR <Xn>


Decode for this encoding

 integer n = UInt(Rn);
 BranchType branch_type;

 case op of
     when '00' branch_type = BranchType_JMP;
     when '01' branch_type = BranchType_CALL;
     when '10' branch_type = BranchType_RET;
     otherwise UnallocatedEncoding();


Assembler symbols

<Xn>          Is the 64-bit name of the general-purpose register holding the address to be branched to, encoded in
              the "Rn" field.


Operation

 bits(64) target = X[n];

 if branch_type == BranchType_CALL then X[30] = PC[] + 4;
 BranchTo(target, branch_type);


platform: ARM
mnem: BRK
description:
Self-hosted debug breakpoint       (C6.6.29)




    31 30 29 28 27 26 25 24 23 22 21 20                                              5 4 3 2 1 0
    1 1 0 1 0 1 0 0 0 0 1                                 imm16                         0 0 0 0 0




System variant

BRK #<imm>


Decode for this encoding

  bits(16) comment = imm16;


Assembler symbols

<imm>           Is a 16-bit unsigned immediate, in the range 0 to 65535, encoded in the "imm16" field.


Operation

  AArch64.SoftwareBreakpoint(comment);


platform: ARM
mnem: CBNZ
description:
Compare and Branch on Nonzero compares the value in a register with zero, and conditionally branches to a label       (C6.6.30)
at a PC-relative offset if the comparison is not equal. It provides a hint that this is not a subroutine call or return.
This instruction does not affect the condition flags.




  31 30 29 28 27 26 25 24 23                                                              5 4             0
   sf 0 1 1 0 1 0 1                                     imm19                                      Rt
                          op


32-bit variant

Applies when sf = 0.

CBNZ <Wt>, <label>


64-bit variant

Applies when sf = 1.

CBNZ <Xt>, <label>


Decode for all variants of this encoding

 integer t = UInt(Rt);
 integer datasize = if sf == '1' then 64 else 32;
 boolean iszero = (op == '0');
 bits(64) offset = SignExtend(imm19:'00', 64);


Assembler symbols

<Wt>            Is the 32-bit name of the general-purpose register to be tested, encoded in the "Rt" field.

<Xt>            Is the 64-bit name of the general-purpose register to be tested, encoded in the "Rt" field.

<label>         Is the program label to be conditionally branched to. Its offset from the address of this instruction,
                in the range +/-1MB, is encoded as "imm19" times 4.


Operation

 bits(datasize) operand1 = X[t];

 if IsZero(operand1) == iszero then
     BranchTo(PC[] + offset, BranchType_JMP);


platform: ARM
mnem: CBZ
description:
Compare and Branch on Zero compares the value in a register with zero, and conditionally branches to a label at a       (C6.6.31)
PC-relative offset if the comparison is equal. It provides a hint that this is not a subroutine call or return. This
instruction does not affect condition flags.




    31 30 29 28 27 26 25 24 23                                                           5 4               0
    sf 0 1 1 0 1 0 0                                   imm19                                       Rt
                          op


32-bit variant

Applies when sf = 0.

CBZ <Wt>, <label>


64-bit variant

Applies when sf = 1.

CBZ <Xt>, <label>


Decode for all variants of this encoding

  integer t = UInt(Rt);
  integer datasize = if sf == '1' then 64 else 32;
  boolean iszero = (op == '0');
  bits(64) offset = SignExtend(imm19:'00', 64);


Assembler symbols

<Wt>            Is the 32-bit name of the general-purpose register to be tested, encoded in the "Rt" field.

<Xt>            Is the 64-bit name of the general-purpose register to be tested, encoded in the "Rt" field.

<label>         Is the program label to be conditionally branched to. Its offset from the address of this instruction,
                in the range +/-1MB, is encoded as "imm19" times 4.


Operation

  bits(datasize) operand1 = X[t];

  if IsZero(operand1) == iszero then
       BranchTo(PC[] + offset, BranchType_JMP);


platform: ARM
mnem: CCMN
description:
Conditional compare negative (immediate), setting condition flags to result of comparison or an immediate value:       (C6.6.32)
flags = if cond then compare(Rn, #-imm) else #nzcv




  31 30 29 28 27 26 25 24 23 22 21 20            16 15         12 11 10 9             5 4 3            0
  sf 0 1 1 1 0 1 0 0 1 0                  imm5           cond     1 0          Rn         0     nzcv
     op


32-bit variant

Applies when sf = 0.

CCMN <Wn>, #<imm>, #<nzcv>, <cond>


64-bit variant

Applies when sf = 1.

CCMN <Xn>, #<imm>, #<nzcv>, <cond>


Decode for all variants of this encoding

 integer n = UInt(Rn);
 integer datasize = if sf == '1' then 64 else 32;
 boolean sub_op = (op == '1');
 bits(4) condition = cond;
 bits(4) flags = nzcv;
 bits(datasize) imm = ZeroExtend(imm5, datasize);


Assembler symbols

<Wn>          Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Xn>          Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

<imm>         Is a five bit unsigned (positive) immediate encoded in the "imm5" field.

<nzcv>        Is the flag bit specifier, an immediate in the range 0 to 15, giving the alternative state for the 4-bit
              NZCV condition flags, encoded in the "nzcv" field.

<cond>        Is one of the standard conditions, encoded in the "cond" field in the standard way.


Operation

 bits(datasize) operand1 = X[n];
 bits(datasize) operand2 = imm;
 bit carry_in = '0';

 if ConditionHolds(condition) then
     if sub_op then
         operand2 = NOT(operand2);
         carry_in = '1';
     (-, flags) = AddWithCarry(operand1, operand2, carry_in);
 PSTATE.<N,Z,C,V> = flags;


platform: ARM
mnem: CCMP
description:
Conditional compare (immediate), setting condition flags to result of comparison or an immediate value: flags =       (C6.6.34)
if cond then compare(Rn, #imm) else #nzcv




  31 30 29 28 27 26 25 24 23 22 21 20            16 15         12 11 10 9             5 4 3            0
  sf 1 1 1 1 0 1 0 0 1 0                  imm5           cond     1 0          Rn         0     nzcv
     op


32-bit variant

Applies when sf = 0.

CCMP <Wn>, #<imm>, #<nzcv>, <cond>


64-bit variant

Applies when sf = 1.

CCMP <Xn>, #<imm>, #<nzcv>, <cond>


Decode for all variants of this encoding

 integer n = UInt(Rn);
 integer datasize = if sf == '1' then 64 else 32;
 boolean sub_op = (op == '1');
 bits(4) condition = cond;
 bits(4) flags = nzcv;
 bits(datasize) imm = ZeroExtend(imm5, datasize);


Assembler symbols

<Wn>          Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Xn>          Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

<imm>         Is a five bit unsigned (positive) immediate encoded in the "imm5" field.

<nzcv>        Is the flag bit specifier, an immediate in the range 0 to 15, giving the alternative state for the 4-bit
              NZCV condition flags, encoded in the "nzcv" field.

<cond>        Is one of the standard conditions, encoded in the "cond" field in the standard way.


Operation

 bits(datasize) operand1 = X[n];
 bits(datasize) operand2 = imm;
 bit carry_in = '0';

 if ConditionHolds(condition) then
     if sub_op then
         operand2 = NOT(operand2);
         carry_in = '1';
     (-, flags) = AddWithCarry(operand1, operand2, carry_in);
 PSTATE.<N,Z,C,V> = flags;


platform: ARM
mnem: CINC
description:
Conditional increment: Rd = if cond then Rn+1 else Rn       (C6.6.36)

This instruction is an alias of the CSINC instruction. This means that:

.      The encodings in this description are named to match the encodings of CSINC.

.      The description of CSINC gives the operational pseudocode for this instruction.




  31 30 29 28 27 26 25 24 23 22 21 20              16 15      12 11 10 9              5 4              0
   sf 0 0 1 1 0 1 0 1 0 0                !=11111        !=111x    0 1       !=11111            Rd
     op                                    Rm            cond        o2        Rn


32-bit variant

Applies when sf = 0.

CINC <Wd>, <Wn>, <cond>

is equivalent to

CSINC <Wd>, <Wn>, <Wn>, invert(<cond>)

and is the preferred disassembly when Rn == Rm.

64-bit variant

Applies when sf = 1.

CINC <Xd>, <Xn>, <cond>

is equivalent to

CSINC <Xd>, <Xn>, <Xn>, invert(<cond>)

and is the preferred disassembly when Rn == Rm.


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the general-purpose source register, encoded in the "Rn" and "Rm" fields.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the general-purpose source register, encoded in the "Rn" and "Rm" fields.

<cond>          Is one of the standard conditions, excluding AL and NV, encoded in the "cond" field with its least
                significant bit inverted.


Operation

The description of CSINC gives the operational pseudocode for this instruction.


platform: ARM
mnem: CINV
description:
Conditional invert: Rd = if cond then NOT(Rn) else Rn       (C6.6.37)

This instruction is an alias of the CSINV instruction. This means that:

.       The encodings in this description are named to match the encodings of CSINV.

.       The description of CSINV gives the operational pseudocode for this instruction.




    31 30 29 28 27 26 25 24 23 22 21 20           16 15       12 11 10 9             5 4              0
    sf 1 0 1 1 0 1 0 1 0 0                !=11111       !=111x    0 0       !=11111            Rd
       op                                   Rm           cond       o2         Rn


32-bit variant

Applies when sf = 0.

CINV <Wd>, <Wn>, <cond>

is equivalent to

CSINV <Wd>, <Wn>, <Wn>, invert(<cond>)

and is the preferred disassembly when Rn == Rm.

64-bit variant

Applies when sf = 1.

CINV <Xd>, <Xn>, <cond>

is equivalent to

CSINV <Xd>, <Xn>, <Xn>, invert(<cond>)

and is the preferred disassembly when Rn == Rm.


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the general-purpose source register, encoded in the "Rn" and "Rm" fields.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the general-purpose source register, encoded in the "Rn" and "Rm" fields.

<cond>          Is one of the standard conditions, excluding AL and NV, encoded in the "cond" field with its least
                significant bit inverted.


Operation

The description of CSINV gives the operational pseudocode for this instruction.


platform: ARM
mnem: CLREX
description:
Clear exclusive monitor       (C6.6.38)




  31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11           8 7 6 5 4 3 2 1 0
  1 1 0 1 0 1 0 1 0 0 0 0 0 0 1 1 0 0 1 1                           CRm       0 1 0 1 1 1 1 1




System variant

CLREX {#<imm>}


Decode for this encoding

 // CRm field is ignored


Assembler symbols

<imm>          Is an optional 4-bit unsigned immediate, in the range 0 to 15, defaulting to 15 and encoded in the
               "CRm" field.


Operation

 ClearExclusiveLocal(ProcessorID());


platform: ARM
mnem: CLS
description:
Count leading sign bits: Rd = CLS(Rn)       (C6.6.39)




    31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9              5 4              0
    sf 1 0 1 1 0 1 0 1 1 0 0 0 0 0 0 0 0 0 1 0 1                               Rn              Rd
                                                                    op


32-bit variant

Applies when sf = 0.

CLS <Wd>, <Wn>


64-bit variant

Applies when sf = 1.

CLS <Xd>, <Xn>


Decode for all variants of this encoding

  integer d = UInt(Rd);
  integer n = UInt(Rn);
  integer datasize = if sf == '1' then 64 else 32;
  CountOp opcode = if op == '0' then CountOp_CLZ else CountOp_CLS;


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the general-purpose source register, encoded in the "Rn" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the general-purpose source register, encoded in the "Rn" field.


Operation

  integer result;
  bits(datasize) operand1 = X[n];

  if opcode == CountOp_CLZ then
       result = CountLeadingZeroBits(operand1);
  else
       result = CountLeadingSignBits(operand1);

  X[d] = result<datasize-1:0>;


platform: ARM
mnem: CLZ
description:
Count leading zero bits: Rd = CLZ(Rn)       (C6.6.40)




  31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9               5 4              0
  sf 1 0 1 1 0 1 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0                               Rn              Rd
                                                                  op


32-bit variant

Applies when sf = 0.

CLZ <Wd>, <Wn>


64-bit variant

Applies when sf = 1.

CLZ <Xd>, <Xn>


Decode for all variants of this encoding

 integer d = UInt(Rd);
 integer n = UInt(Rn);
 integer datasize = if sf == '1' then 64 else 32;
 CountOp opcode = if op == '0' then CountOp_CLZ else CountOp_CLS;


Assembler symbols

<Wd>          Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>          Is the 32-bit name of the general-purpose source register, encoded in the "Rn" field.

<Xd>          Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>          Is the 64-bit name of the general-purpose source register, encoded in the "Rn" field.


Operation

 integer result;
 bits(datasize) operand1 = X[n];

 if opcode == CountOp_CLZ then
     result = CountLeadingZeroBits(operand1);
 else
     result = CountLeadingSignBits(operand1);

 X[d] = result<datasize-1:0>;


platform: ARM
mnem: CMN
description:
       Compare negative (extended register), setting the condition flags and discarding the result: Rn + LSL(extend(Rm),       (C6.6.41)
       amount)

       This instruction is an alias of the ADDS (extended register) instruction. This means that:

       .       The encodings in this description are named to match the encodings of ADDS (extended register).

       .       The description of ADDS (extended register) gives the operational pseudocode for this instruction.




           31 30 29 28 27 26 25 24 23 22 21 20            16 15     13 12      10 9            5 4            0
           sf 0 1 0 1 0 1 1 0 0 1                  Rm          option    imm3           Rn        1 1 1 1 1
              op S                                                                                      Rd


       32-bit variant

       Applies when sf = 0.

       CMN <Wn|WSP>, <Wm>{, <extend> {#<amount>}}

       is equivalent to

       ADDS WZR, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}

       and is always the preferred disassembly.

       64-bit variant

       Applies when sf = 1.

       CMN <Xn|SP>, <R><m>{, <extend> {#<amount>}}

       is equivalent to

       ADDS XZR, <Xn|SP>, <R><m>{, <extend> {#<amount>}}

       and is always the preferred disassembly.


       Assembler symbols

       <Wn|WSP>        Is the 32-bit name of the first source general-purpose register or stack pointer, encoded in the "Rn"
                       field.

       <Wm>            Is the 32-bit name of the second general-purpose source register, encoded in the "Rm" field.

       <Xn|SP>         Is the 64-bit name of the first source general-purpose register or stack pointer, encoded in the "Rn"
                       field.

       <R>             Is a width specifier, encoded in the "option" field. It can have the following values:

                       W            when option = 00x

                       W            when option = 010

                       X            when option = x11

                       W            when option = 10x

                       W            when option = 110

       <m>             Is the number [0-30] of the second general-purpose source register or the name ZR (31), encoded in
                       the "Rm" field.
<extend>       For the 32-bit variant: is the extension to be applied to the second source operand, encoded in the
               "option" field. It can have the following values:

               UXTB         when option = 000

               UXTH         when option = 001

               LSL|UXTW     when option = 010

               UXTX         when option = 011

               SXTB         when option = 100

               SXTH         when option = 101

               SXTW         when option = 110

               SXTX         when option = 111

               If "Rn" is '11111' (WSP) and "option" is '010' then LSL is preferred, but may be omitted when
               "imm3" is '000'. In all other cases <extend> is required and must be UXTW when "option" is '010'.

               For the 64-bit variant: is the extension to be applied to the second source operand, encoded in the
               "option" field. It can have the following values:

               UXTB         when option = 000

               UXTH         when option = 001

               UXTW         when option = 010

               LSL|UXTX     when option = 011

               SXTB         when option = 100

               SXTH         when option = 101

               SXTW         when option = 110

               SXTX         when option = 111

               If "Rn" is '11111' (SP) and "option" is '011' then LSL is preferred, but may be omitted when "imm3"
               is '000'. In all other cases <extend> is required and must be UXTX when "option" is '011'.

<amount>       Is the left shift amount to be applied after extension in the range 0 to 4, defaulting to 0, encoded in
               the "imm3" field. It must be absent when <extend> is absent, is required when <extend> is LSL,
               and is optional when <extend> is present but not LSL.


Operation

The description of ADDS (extended register) gives the operational pseudocode for this instruction.


platform: ARM
mnem: CMP
description:
Compare (extended register), setting the condition flags and discarding the result: Rn - LSL(extend(Rm), amount)       (C6.6.44)

This instruction is an alias of the SUBS (extended register) instruction. This means that:

.      The encodings in this description are named to match the encodings of SUBS (extended register).

.      The description of SUBS (extended register) gives the operational pseudocode for this instruction.




  31 30 29 28 27 26 25 24 23 22 21 20              16 15     13 12      10 9            5 4             0
   sf 1 1 0 1 0 1 1 0 0 1                   Rm          option    imm3           Rn        1 1 1 1 1
     op S                                                                                        Rd


32-bit variant

Applies when sf = 0.

CMP <Wn|WSP>, <Wm>{, <extend> {#<amount>}}

is equivalent to

SUBS WZR, <Wn|WSP>, <Wm>{, <extend> {#<amount>}}

and is always the preferred disassembly.

64-bit variant

Applies when sf = 1.

CMP <Xn|SP>, <R><m>{, <extend> {#<amount>}}

is equivalent to

SUBS XZR, <Xn|SP>, <R><m>{, <extend> {#<amount>}}

and is always the preferred disassembly.


Assembler symbols

<Wn|WSP>        Is the 32-bit name of the first source general-purpose register or stack pointer, encoded in the "Rn"
                field.

<Wm>            Is the 32-bit name of the second general-purpose source register, encoded in the "Rm" field.

<Xn|SP>         Is the 64-bit name of the first source general-purpose register or stack pointer, encoded in the "Rn"
                field.

<R>             Is a width specifier, encoded in the "option" field. It can have the following values:

                W            when option = 00x

                W            when option = 010

                X            when option = x11

                W            when option = 10x

                W            when option = 110

<m>             Is the number [0-30] of the second general-purpose source register or the name ZR (31), encoded in
                the "Rm" field.
       <extend>        For the 32-bit variant: is the extension to be applied to the second source operand, encoded in the
                       "option" field. It can have the following values:

                       UXTB         when option = 000

                       UXTH         when option = 001

                       LSL|UXTW     when option = 010

                       UXTX         when option = 011

                       SXTB         when option = 100

                       SXTH         when option = 101

                       SXTW         when option = 110

                       SXTX         when option = 111

                       If "Rn" is '11111' (WSP) and "option" is '010' then LSL is preferred, but may be omitted when
                       "imm3" is '000'. In all other cases <extend> is required and must be UXTW when "option" is '010'.

                       For the 64-bit variant: is the extension to be applied to the second source operand, encoded in the
                       "option" field. It can have the following values:

                       UXTB         when option = 000

                       UXTH         when option = 001

                       UXTW         when option = 010

                       LSL|UXTX     when option = 011

                       SXTB         when option = 100

                       SXTH         when option = 101

                       SXTW         when option = 110

                       SXTX         when option = 111

                       If "Rn" is '11111' (SP) and "option" is '011' then LSL is preferred, but may be omitted when "imm3"
                       is '000'. In all other cases <extend> is required and must be UXTX when "option" is '011'.

       <amount>        Is the left shift amount to be applied after extension in the range 0 to 4, defaulting to 0, encoded in
                       the "imm3" field. It must be absent when <extend> is absent, is required when <extend> is LSL,
                       and is optional when <extend> is present but not LSL.


       Operation

       The description of SUBS (extended register) gives the operational pseudocode for this instruction.


platform: ARM
mnem: CNEG
description:
Conditional negate: Rd = if cond then -Rn else Rn       (C6.6.47)

This instruction is an alias of the CSNEG instruction. This means that:

.       The encodings in this description are named to match the encodings of CSNEG.

.       The description of CSNEG gives the operational pseudocode for this instruction.




    31 30 29 28 27 26 25 24 23 22 21 20           16 15       12 11 10 9             5 4              0
    sf 1 0 1 1 0 1 0 1 0 0                  Rm          !=111x    0 1          Rn              Rd
       op                                                cond       o2


32-bit variant

Applies when sf = 0.

CNEG <Wd>, <Wn>, <cond>

is equivalent to

CSNEG <Wd>, <Wn>, <Wn>, invert(<cond>)

and is the preferred disassembly when Rn == Rm.

64-bit variant

Applies when sf = 1.

CNEG <Xd>, <Xn>, <cond>

is equivalent to

CSNEG <Xd>, <Xn>, <Xn>, invert(<cond>)

and is the preferred disassembly when Rn == Rm.


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the general-purpose source register, encoded in the "Rn" and "Rm" fields.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the general-purpose source register, encoded in the "Rn" and "Rm" fields.

<cond>          Is one of the standard conditions, excluding AL and NV, encoded in the "cond" field with its least
                significant bit inverted.


Operation

The description of CSNEG gives the operational pseudocode for this instruction.


platform: ARM
mnem: CRC32B
description:
CRC-32 checksum from byte, halfword, word or doubleword: Wd = CRC32(Wn, Rm<n:0>) // n = 7, 15, 31, 63       (C6.6.48)




  31 30 29 28 27 26 25 24 23 22 21 20           16 15 14 13 12 11 10 9             5 4              0
  sf 0 0 1 1 0 1 0 1 1 0                 Rm        0 1 0 0       sz          Rn              Rd
                                                             C


CRC32B variant

Applies when sf = 0 && sz = 00.

CRC32B <Wd>, <Wn>, <Wm>


CRC32H variant

Applies when sf = 0 && sz = 01.

CRC32H <Wd>, <Wn>, <Wm>


CRC32W variant

Applies when sf = 0 && sz = 10.

CRC32W <Wd>, <Wn>, <Wm>


CRC32X variant

Applies when sf = 1 && sz = 11.

CRC32X <Wd>, <Wn>, <Xm>


Decode for all variants of this encoding

 integer d = UInt(Rd);
 integer n = UInt(Rn);
 integer m = UInt(Rm);
 if sf == '1' && sz != '11' then UnallocatedEncoding();
 if sf == '0' && sz == '11' then UnallocatedEncoding();
 integer size = 8 << UInt(sz);   // 2-bit size field -> 8, 16, 32, 64
 boolean crc32c = (C == '1');


Assembler symbols

<Wd>          Is the 32-bit name of the general-purpose accumulator output register, encoded in the "Rd" field.

<Wn>          Is the 32-bit name of the general-purpose accumulator input register, encoded in the "Rn" field.

<Xm>          Is the 64-bit name of the general-purpose data source register, encoded in the "Rm" field.

<Wm>          Is the 32-bit name of the general-purpose data source register, encoded in the "Rm" field.


Operation

 if !HaveCRCExt() then
     UnallocatedEncoding();

 bits(32)      acc     = X[n];   // accumulator
 bits(size)    val     = X[m];   // input value
 bits(32)      poly    = (if crc32c then 0x1EDC6F41 else 0x04C11DB7)<31:0>;
         bits(32+size) tempacc = BitReverse(acc) : Zeros(size);
         bits(size+32) tempval = BitReverse(val) : Zeros(32);

         // Poly32Mod2 on a bitstring does a polynomial Modulus over {0,1} operation
         X[d] = BitReverse(Poly32Mod2(tempacc EOR tempval, poly));


platform: ARM
mnem: CRC32CB
description:
CRC-32C checksum from byte, halfword, word, or doubleword: Wd = CRC32C(Wn, Rm<n:0>) // n = 7, 15, 31, 63       (C6.6.49)




  31 30 29 28 27 26 25 24 23 22 21 20           16 15 14 13 12 11 10 9             5 4              0
  sf 0 0 1 1 0 1 0 1 1 0                 Rm        0 1 0 1       sz          Rn              Rd
                                                             C


CRC32CB variant

Applies when sf = 0 && sz = 00.

CRC32CB <Wd>, <Wn>, <Wm>


CRC32CH variant

Applies when sf = 0 && sz = 01.

CRC32CH <Wd>, <Wn>, <Wm>


CRC32CW variant

Applies when sf = 0 && sz = 10.

CRC32CW <Wd>, <Wn>, <Wm>


CRC32CX variant

Applies when sf = 1 && sz = 11.

CRC32CX <Wd>, <Wn>, <Xm>


Decode for all variants of this encoding

 integer d = UInt(Rd);
 integer n = UInt(Rn);
 integer m = UInt(Rm);
 if sf == '1' && sz != '11' then UnallocatedEncoding();
 if sf == '0' && sz == '11' then UnallocatedEncoding();
 integer size = 8 << UInt(sz);   // 2-bit size field -> 8, 16, 32, 64
 boolean crc32c = (C == '1');


Assembler symbols

<Wd>          Is the 32-bit name of the general-purpose accumulator output register, encoded in the "Rd" field.

<Wn>          Is the 32-bit name of the general-purpose accumulator input register, encoded in the "Rn" field.

<Xm>          Is the 64-bit name of the general-purpose data source register, encoded in the "Rm" field.

<Wm>          Is the 32-bit name of the general-purpose data source register, encoded in the "Rm" field.


Operation

 if !HaveCRCExt() then
     UnallocatedEncoding();

 bits(32)      acc     = X[n];   // accumulator
 bits(size)    val     = X[m];   // input value
 bits(32)      poly    = (if crc32c then 0x1EDC6F41 else 0x04C11DB7)<31:0>;
         bits(32+size) tempacc = BitReverse(acc) : Zeros(size);
         bits(size+32) tempval = BitReverse(val) : Zeros(32);

         // Poly32Mod2 on a bitstring does a polynomial Modulus over {0,1} operation
         X[d] = BitReverse(Poly32Mod2(tempacc EOR tempval, poly));


platform: ARM
mnem: CSEL
description:
Conditional select, returning the first or second input: Rd = if cond then Rn else Rm       (C6.6.50)




  31 30 29 28 27 26 25 24 23 22 21 20              16 15        12 11 10 9            5 4              0
  sf 0 0 1 1 0 1 0 1 0 0                     Rm           cond     0 0         Rn              Rd
     op                                                               o2


32-bit variant

Applies when sf = 0.

CSEL <Wd>, <Wn>, <Wm>, <cond>


64-bit variant

Applies when sf = 1.

CSEL <Xd>, <Xn>, <Xm>, <cond>


Decode for all variants of this encoding

 integer d = UInt(Rd);
 integer n = UInt(Rn);
 integer m = UInt(Rm);
 integer datasize = if sf == '1' then 64 else 32;
 bits(4) condition = cond;
 boolean else_inv = (op == '1');
 boolean else_inc = (o2 == '1');


Assembler symbols

<Wd>           Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>           Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Wm>           Is the 32-bit name of the second general-purpose source register, encoded in the "Rm" field.

<Xd>           Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>           Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Xm>           Is the 64-bit name of the second general-purpose source register, encoded in the "Rm" field.

<cond>         Is one of the standard conditions, encoded in the "cond" field in the standard way.


Operation

 bits(datasize) result;
 bits(datasize) operand1 = X[n];
 bits(datasize) operand2 = X[m];

 if ConditionHolds(condition) then
     result = operand1;
 else
     result = operand2;
     if else_inv then result = NOT(result);
     if else_inc then result = result + 1;

 X[d] = result;


platform: ARM
mnem: CSET
description:
Conditional set: Rd = if cond then 1 else 0       (C6.6.51)

This instruction is an alias of the CSINC instruction. This means that:

.       The encodings in this description are named to match the encodings of CSINC.

.       The description of CSINC gives the operational pseudocode for this instruction.




    31 30 29 28 27 26 25 24 23 22 21 20            16 15      12 11 10 9             5 4              0
    sf 0 0 1 1 0 1 0 1 0 0 1 1 1 1 1                    !=111x    0 1 1 1 1 1 1                Rd
       op                                   Rm           cond        o2        Rn


32-bit variant

Applies when sf = 0.

CSET <Wd>, <cond>

is equivalent to

CSINC <Wd>, WZR, WZR, invert(<cond>)

and is always the preferred disassembly.

64-bit variant

Applies when sf = 1.

CSET <Xd>, <cond>

is equivalent to

CSINC <Xd>, XZR, XZR, invert(<cond>)

and is always the preferred disassembly.


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<cond>          Is one of the standard conditions, excluding AL and NV, encoded in the "cond" field with its least
                significant bit inverted.


Operation

The description of CSINC gives the operational pseudocode for this instruction.


platform: ARM
mnem: CSETM
description:
Conditional set mask: Rd = if cond then -1 else 0       (C6.6.52)

This instruction is an alias of the CSINV instruction. This means that:

.      The encodings in this description are named to match the encodings of CSINV.

.      The description of CSINV gives the operational pseudocode for this instruction.




  31 30 29 28 27 26 25 24 23 22 21 20             16 15       12 11 10 9              5 4              0
   sf 1 0 1 1 0 1 0 1 0 0 1 1 1 1 1                     !=111x    0 0 1 1 1 1 1                Rd
     op                                    Rm            cond       o2         Rn


32-bit variant

Applies when sf = 0.

CSETM <Wd>, <cond>

is equivalent to

CSINV <Wd>, WZR, WZR, invert(<cond>)

and is always the preferred disassembly.

64-bit variant

Applies when sf = 1.

CSETM <Xd>, <cond>

is equivalent to

CSINV <Xd>, XZR, XZR, invert(<cond>)

and is always the preferred disassembly.


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<cond>          Is one of the standard conditions, excluding AL and NV, encoded in the "cond" field with its least
                significant bit inverted.


Operation

The description of CSINV gives the operational pseudocode for this instruction.


platform: ARM
mnem: CSINC
description:
       Conditional select increment, returning the first input or incremented second input: Rd = if cond then Rn else (Rm       (C6.6.53)
       + 1)

       This instruction is used by the aliases CINC and CSET. See the Alias conditions table for details of when each alias
       is preferred.




           31 30 29 28 27 26 25 24 23 22 21 20            16 15        12 11 10 9             5 4             0
           sf 0 0 1 1 0 1 0 1 0 0                  Rm             cond    0 1          Rn              Rd
              op                                                             o2


       32-bit variant

       Applies when sf = 0.

       CSINC <Wd>, <Wn>, <Wm>, <cond>


       64-bit variant

       Applies when sf = 1.

       CSINC <Xd>, <Xn>, <Xm>, <cond>


       Decode for all variants of this encoding

         integer d = UInt(Rd);
         integer n = UInt(Rn);
         integer m = UInt(Rm);
         integer datasize = if sf == '1' then 64 else 32;
         bits(4) condition = cond;
         boolean else_inv = (op == '1');
         boolean else_inc = (o2 == '1');


       Alias conditions


                            Alias                     is preferred when

                            CINC                      Rm != '11111' && cond != '111x' && Rn != '11111' && Rn == Rm

                            CSET                      Rm == '11111' && cond != '111x' && Rn == '11111'



       Assembler symbols

       <Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <Wn>            Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

       <Wm>            Is the 32-bit name of the second general-purpose source register, encoded in the "Rm" field.

       <Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <Xn>            Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

       <Xm>            Is the 64-bit name of the second general-purpose source register, encoded in the "Rm" field.

       <cond>          Is one of the standard conditions, encoded in the "cond" field in the standard way.
Operation

 bits(datasize) result;
 bits(datasize) operand1 = X[n];
 bits(datasize) operand2 = X[m];

 if ConditionHolds(condition) then
    result = operand1;
 else
    result = operand2;
    if else_inv then result = NOT(result);
    if else_inc then result = result + 1;

 X[d] = result;


platform: ARM
mnem: CSINV
description:
       Conditional select inversion, returning the first input or inverted second input: Rd = if cond then Rn else NOT (Rm)       (C6.6.54)

       This instruction is used by the aliases CINV and CSETM. See the Alias conditions table for details of when each
       alias is preferred.




           31 30 29 28 27 26 25 24 23 22 21 20             16 15        12 11 10 9             5 4             0
           sf 1 0 1 1 0 1 0 1 0 0                   Rm            cond      0 0         Rn              Rd
              op                                                              o2


       32-bit variant

       Applies when sf = 0.

       CSINV <Wd>, <Wn>, <Wm>, <cond>


       64-bit variant

       Applies when sf = 1.

       CSINV <Xd>, <Xn>, <Xm>, <cond>


       Decode for all variants of this encoding

         integer d = UInt(Rd);
         integer n = UInt(Rn);
         integer m = UInt(Rm);
         integer datasize = if sf == '1' then 64 else 32;
         bits(4) condition = cond;
         boolean else_inv = (op == '1');
         boolean else_inc = (o2 == '1');


       Alias conditions


                             Alias                     is preferred when

                             CINV                      Rm != '11111' && cond != '111x' && Rn != '11111' && Rn == Rm

                             CSETM                     Rm == '11111' && cond != '111x' && Rn == '11111'



       Assembler symbols

       <Wd>             Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <Wn>             Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

       <Wm>             Is the 32-bit name of the second general-purpose source register, encoded in the "Rm" field.

       <Xd>             Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <Xn>             Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

       <Xm>             Is the 64-bit name of the second general-purpose source register, encoded in the "Rm" field.

       <cond>           Is one of the standard conditions, encoded in the "cond" field in the standard way.
Operation

 bits(datasize) result;
 bits(datasize) operand1 = X[n];
 bits(datasize) operand2 = X[m];

 if ConditionHolds(condition) then
    result = operand1;
 else
    result = operand2;
    if else_inv then result = NOT(result);
    if else_inc then result = result + 1;

 X[d] = result;


platform: ARM
mnem: CSNEG
description:
      Conditional select negation, returning the first input or negated second input: Rd = if cond then Rn else -Rm       (C6.6.55)

      This instruction is used by the alias CNEG. See the Alias conditions table for details of when each alias is preferred.




          31 30 29 28 27 26 25 24 23 22 21 20            16 15        12 11 10 9              5 4            0
          sf 1 0 1 1 0 1 0 1 0 0                  Rm            cond      0 1         Rn              Rd
             op                                                             o2


      32-bit variant

      Applies when sf = 0.

      CSNEG <Wd>, <Wn>, <Wm>, <cond>


      64-bit variant

      Applies when sf = 1.

      CSNEG <Xd>, <Xn>, <Xm>, <cond>


      Decode for all variants of this encoding

        integer d = UInt(Rd);
        integer n = UInt(Rn);
        integer m = UInt(Rm);
        integer datasize = if sf == '1' then 64 else 32;
        bits(4) condition = cond;
        boolean else_inv = (op == '1');
        boolean else_inc = (o2 == '1');


      Alias conditions


                           Alias                     is preferred when

                           CNEG                      cond != '111x' && Rn == Rm



      Assembler symbols

      <Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

      <Wn>            Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

      <Wm>            Is the 32-bit name of the second general-purpose source register, encoded in the "Rm" field.

      <Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

      <Xn>            Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

      <Xm>            Is the 64-bit name of the second general-purpose source register, encoded in the "Rm" field.

      <cond>          Is one of the standard conditions, encoded in the "cond" field in the standard way.


      Operation

        bits(datasize) result;
        bits(datasize) operand1 = X[n];
        bits(datasize) operand2 = X[m];

if ConditionHolds(condition) then
   result = operand1;
else
   result = operand2;
   if else_inv then result = NOT(result);
   if else_inc then result = result + 1;

X[d] = result;


platform: ARM
mnem: DC
description:
Data cache operation       (C6.6.56)

This instruction is an alias of the SYS instruction. This means that:

.       The encodings in this description are named to match the encodings of SYS.

.       The description of SYS gives the operational pseudocode for this instruction.




    31 30 29 28 27 26 25 24 23 22 21 20 19 18      16 15        12 11       8 7      5 4             0
    1 1 0 1 0 1 0 1 0 0 0 0 1                  op1     0 1 1 1        CRm        op2           Rt
                                    L                     CRn


System variant

DC <dc_op>, <Xt>

is equivalent to

SYS #<op1>, C7, <Cm>, #<op2>, <Xt>

and is the preferred disassembly when SysOp(op1,'0111',CRm,op2) == Sys_DC.


Assembler symbols

<dc_op>         Is a DC operation name, as listed for the DC system operation group, encoded in the
                "op1:CRm:op2" field. It can have the following values:

                IVAC         when op1 = 000, CRm = 0110, op2 = 001

                ISW          when op1 = 000, CRm = 0110, op2 = 010

                CSW          when op1 = 000, CRm = 1010, op2 = 010

                CISW         when op1 = 000, CRm = 1110, op2 = 010

                ZVA          when op1 = 011, CRm = 0100, op2 = 001

                CVAC         when op1 = 011, CRm = 1010, op2 = 001

                CVAU         when op1 = 011, CRm = 1011, op2 = 001

                CIVAC        when op1 = 011, CRm = 1110, op2 = 001

<op1>           Is a 3-bit unsigned immediate, in the range 0 to 7, encoded in the "op1" field.

<Cm>            Is a name 'Cm', with 'm' in the range 0 to 15, encoded in the "CRm" field.

<op2>           Is a 3-bit unsigned immediate, in the range 0 to 7, encoded in the "op2" field.

<Xt>            Is the 64-bit name of the general-purpose source register, encoded in the "Rt" field.


Operation

The description of SYS gives the operational pseudocode for this instruction.


platform: ARM
mnem: DCPS1
description:
Debug Change PE State to EL1 allows the debugger to move the PE into EL1 from a lower Exception Level or to       (C6.6.57)
a specific mode at the current Exception Level.

If the PE is at EL1 or lower, then the PE enters EL1h.

If the PE is at an Exception Level higher than EL1, then the PE does not change Exception Level but selects use of
the stack pointer for the current Exception Level by updating PSTATE.SP.

This instruction is always UNDEFINED in Non-debug state.

For more information on the operation of this instructions, see DCPS on page H2-4963.




  31 30 29 28 27 26 25 24 23 22 21 20                                                 5 4 3 2 1 0
   1 1 0 1 0 1 0 0 1 0 1                                   imm16                        0 0 0 0 1
                                                                                                    LL


System variant

DCPS1 {#<imm>}


Decode for this encoding

 bits(2) target_level = LL;
 if LL == '00' then UnallocatedEncoding();
 if !Halted() then AArch64.UndefinedFault();


Assembler symbols

<imm>            Is an optional 16-bit unsigned immediate, in the range 0 to 65535, defaulting to 0 and encoded in
                 the "imm16" field.


Operation

 DCPSInstruction(target_level);


platform: ARM
mnem: DCPS2
description:
Debug Change PE State to EL2 allows the debugger to move the PE into EL2 from a lower Exception Level or to       (C6.6.58)
a specific mode at the current Exception Level.

If the PE is at EL2 or lower, then the PE enters EL2h.

If the PE is at an Exception Level higher than EL2, then the PE does not change Exception Level but selects use of
the stack pointer for the current Exception Level by updating PSTATE.SP.

This instruction is always UNDEFINED in Non-debug state.

For more information on the operation of this instructions, see DCPS on page H2-4963.




    31 30 29 28 27 26 25 24 23 22 21 20                                               5 4 3 2 1 0
    1 1 0 1 0 1 0 0 1 0 1                                  imm16                        0 0 0 1 0
                                                                                                    LL


System variant

DCPS2 {#<imm>}


Decode for this encoding

  bits(2) target_level = LL;
  if LL == '00' then UnallocatedEncoding();
  if !Halted() then AArch64.UndefinedFault();


Assembler symbols

<imm>            Is an optional 16-bit unsigned immediate, in the range 0 to 65535, defaulting to 0 and encoded in
                 the "imm16" field.


Operation

  DCPSInstruction(target_level);


platform: ARM
mnem: DCPS3
description:
Debug Change PE State to EL3 allows the debugger to move the PE into EL3 from a lower Exception Level or to       (C6.6.59)
a specific mode at the current Exception Level. The PE enters EL3h.

This instruction is always UNDEFINED in Non-debug state.

For more information on the operation of this instructions, see DCPS on page H2-4963.




  31 30 29 28 27 26 25 24 23 22 21 20                                                5 4 3 2 1 0
   1 1 0 1 0 1 0 0 1 0 1                                   imm16                       0 0 0 1 1
                                                                                                   LL


System variant

DCPS3 {#<imm>}


Decode for this encoding

 bits(2) target_level = LL;
 if LL == '00' then UnallocatedEncoding();
 if !Halted() then AArch64.UndefinedFault();


Assembler symbols

<imm>           Is an optional 16-bit unsigned immediate, in the range 0 to 65535, defaulting to 0 and encoded in
                the "imm16" field.


Operation

 DCPSInstruction(target_level);


platform: ARM
mnem: DMB
description:
       Data memory barrier       (C6.6.60)




           31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11            8 7 6 5 4 3 2 1 0
           1 1 0 1 0 1 0 1 0 0 0 0 0 0 1 1 0 0 1 1                            CRm       1 0 1 1 1 1 1 1
                                                                                            opc


       System variant

       DMB <option>|#<imm>


       Decode for this encoding

         MemBarrierOp op;
         MBReqDomain domain;
         MBReqTypes types;

         case opc of
              when '00' op = MemBarrierOp_DSB;
              when '01' op = MemBarrierOp_DMB;
              when '10' op = MemBarrierOp_ISB;
              otherwise UnallocatedEncoding();

         case CRm<3:2> of
              when '00' domain = MBReqDomain_OuterShareable;
              when '01' domain = MBReqDomain_Nonshareable;
              when '10' domain = MBReqDomain_InnerShareable;
              when '11' domain = MBReqDomain_FullSystem;

         case CRm<1:0> of
              when '01' types = MBReqTypes_Reads;
              when '10' types = MBReqTypes_Writes;
              when '11' types = MBReqTypes_All;
              otherwise
                   types = MBReqTypes_All;
                   domain = MBReqDomain_FullSystem;


       Assembler symbols

       <option>         Specifies the limitation on the barrier operation. Values are:

                        SY          Full system is the required shareability domain, reads and writes are the required access
                                    types in both Group A on page B2-85 and Group B on page B2-86. This option is
                                    referred to as the full system DMB. Encoded as CRm = 0b1111.

                        ST          Full system is the required shareability domain, writes are the required access type in
                                    both Group A on page B2-85 and Group B on page B2-86. Encoded as CRm = 0b1110.

                        LD          Full system is the required shareability domain, reads are the required access type in
                                    Group A on page B2-85, and reads and writes are the required access types in both
                                    Group A on page B2-85 and Group B on page B2-86. Encoded as CRm = 0b1101.

                        ISH         Inner Shareable is the required shareability domain, reads and writes are the required
                                    access types in Group B on page B2-86. Encoded as CRm = 0b1011.

                        ISHST       Inner Shareable is the required shareability domain, writes are the required access type
                                    in both Group A on page B2-85 and Group B on page B2-86. Encoded as CRm = 0b1010.

                        ISHLD       Inner Shareable is the required shareability domain, reads are the required access type
                                    in Group A on page B2-85. Encoded as CRm = 0b1001.

                        NSH         Non-shareable is the required shareability domain, reads and writes are the required
                                    access types in Group B on page B2-86. Encoded as CRm = 0b0111.
              NSHST       Non-shareable is the required shareability domain, writes are the required access type
                          in both Group A on page B2-85 and Group B on page B2-86. Encoded as CRm = 0b0110.

              NSHLD       Non-shareable is the required shareability domain, reads are the required access type in
                          Group A on page B2-85. Encoded as CRm = 0b0101.

              OSH         Outer Shareable is the required shareability domain, reads and writes are the required
                          access types in Group B on page B2-86. Encoded as CRm = 0b0011.

              OSHST       Outer Shareable is the required shareability domain, writes are the required access type
                          in both Group A on page B2-85 and Group B on page B2-86. Encoded as CRm = 0b0010.

              OSHLD       Outer Shareable is the required shareability domain, reads are the required access type
                          in Group A on page B2-85. Encoded as CRm = 0b0001.

               All other encodings of CRm that are not listed above are reserved, and can be encoded using the
              #<imm> syntax. It is IMPLEMENTATION DEFINED whether options other than SY are implemented. All
              unsupported and reserved options must execute as a full system operation, but software must not
              rely on this behavior.

<imm>         Is a 4-bit unsigned immediate, in the range 0 to 15, encoded in the "CRm" field.


Operation

 case op of
    when MemBarrierOp_DSB
         DataSynchronizationBarrier(domain, types);
    when MemBarrierOp_DMB
         DataMemoryBarrier(domain, types);
    when MemBarrierOp_ISB
         InstructionSynchronizationBarrier();


platform: ARM
mnem: DRPS
description:
Debug restore process state       (C6.6.61)




    31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
    1 1 0 1 0 1 1 0 1 0 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0




System variant

DRPS


Decode for this encoding

  if !Halted() || PSTATE.EL == EL0 then UnallocatedEncoding();


Operation

  DRPSInstruction();


platform: ARM
mnem: DSB
description:
Data synchronization barrier       (C6.6.62)




  31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11           8 7 6 5 4 3 2 1 0
  1 1 0 1 0 1 0 1 0 0 0 0 0 0 1 1 0 0 1 1                           CRm       1 0 0 1 1 1 1 1
                                                                                  opc


System variant

DSB <option>|#<imm>


Decode for this encoding

 MemBarrierOp op;
 MBReqDomain domain;
 MBReqTypes types;

 case opc of
     when '00' op = MemBarrierOp_DSB;
     when '01' op = MemBarrierOp_DMB;
     when '10' op = MemBarrierOp_ISB;
     otherwise UnallocatedEncoding();

 case CRm<3:2> of
     when '00' domain = MBReqDomain_OuterShareable;
     when '01' domain = MBReqDomain_Nonshareable;
     when '10' domain = MBReqDomain_InnerShareable;
     when '11' domain = MBReqDomain_FullSystem;

 case CRm<1:0> of
     when '01' types = MBReqTypes_Reads;
     when '10' types = MBReqTypes_Writes;
     when '11' types = MBReqTypes_All;
     otherwise
        types = MBReqTypes_All;
        domain = MBReqDomain_FullSystem;


Assembler symbols

<option>      Specifies the limitation on the barrier operation. Values are:

              SY          Full system is the required shareability domain, reads and writes are the required access
                          types in both Group A on page B2-85 and Group B on page B2-86. This option is
                          referred to as the full system DMB. Encoded as CRm = 0b1111.

              ST          Full system is the required shareability domain, writes are the required access type in
                          both Group A on page B2-85 and Group B on page B2-86. Encoded as CRm = 0b1110.

              LD          Full system is the required shareability domain, reads are the required access type in
                          Group A on page B2-85, and reads and writes are the required access types in both
                          Group A on page B2-85 and Group B on page B2-86. Encoded as CRm = 0b1101.

              ISH         Inner Shareable is the required shareability domain, reads and writes are the required
                          access types in Group B on page B2-86. Encoded as CRm = 0b1011.

              ISHST       Inner Shareable is the required shareability domain, writes are the required access type
                          in both Group A on page B2-85 and Group B on page B2-86. Encoded as CRm = 0b1010.

              ISHLD       Inner Shareable is the required shareability domain, reads are the required access type
                          in Group A on page B2-85. Encoded as CRm = 0b1001.

              NSH         Non-shareable is the required shareability domain, reads and writes are the required
                          access types in Group B on page B2-86. Encoded as CRm = 0b0111.
                        NSHST       Non-shareable is the required shareability domain, writes are the required access type
                                    in both Group A on page B2-85 and Group B on page B2-86. Encoded as CRm = 0b0110.

                        NSHLD       Non-shareable is the required shareability domain, reads are the required access type in
                                    Group A on page B2-85. Encoded as CRm = 0b0101.

                        OSH         Outer Shareable is the required shareability domain, reads and writes are the required
                                    access types in Group B on page B2-86. Encoded as CRm = 0b0011.

                        OSHST       Outer Shareable is the required shareability domain, writes are the required access type
                                    in both Group A on page B2-85 and Group B on page B2-86. Encoded as CRm = 0b0010.

                        OSHLD       Outer Shareable is the required shareability domain, reads are the required access type
                                    in Group A on page B2-85. Encoded as CRm = 0b0001.

                         All other encodings of CRm that are not listed above are reserved, and can be encoded using the
                        #<imm> syntax. It is IMPLEMENTATION DEFINED whether options other than SY are implemented. All
                        unsupported and reserved options must execute as a full system operation, but software must not
                        rely on this behavior.

       <imm>            Is a 4-bit unsigned immediate, in the range 0 to 15, encoded in the "CRm" field.


       Operation

         case op of
              when MemBarrierOp_DSB
                   DataSynchronizationBarrier(domain, types);
              when MemBarrierOp_DMB
                   DataMemoryBarrier(domain, types);
              when MemBarrierOp_ISB
                   InstructionSynchronizationBarrier();


platform: ARM
mnem: EON
description:
Bitwise exclusive OR NOT (shifted register): Rd = Rn EOR NOT shift(Rm, amount)       (C6.6.63)




  31 30 29 28 27 26 25 24 23 22 21 20              16 15               10 9             5 4             0
  sf 1 0 0 1 0 1 0 shift 1                  Rm               imm6                Rn            Rd
     opc                           N


32-bit variant

Applies when sf = 0.

EON <Wd>, <Wn>, <Wm>{, <shift> #<amount>}


64-bit variant

Applies when sf = 1.

EON <Xd>, <Xn>, <Xm>{, <shift> #<amount>}


Decode for all variants of this encoding

 integer d = UInt(Rd);
 integer n = UInt(Rn);
 integer m = UInt(Rm);
 integer datasize = if sf == '1' then 64 else 32;
 boolean setflags;
 LogicalOp op;
 case opc of
     when '00' op = LogicalOp_AND; setflags = FALSE;
     when '01' op = LogicalOp_ORR; setflags = FALSE;
     when '10' op = LogicalOp_EOR; setflags = FALSE;
     when '11' op = LogicalOp_AND; setflags = TRUE;

 if sf == '0' && imm6<5> == '1' then ReservedValue();

 ShiftType shift_type = DecodeShift(shift);
 integer shift_amount = UInt(imm6);
 boolean invert = (N == '1');


Assembler symbols

<Wd>           Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>           Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Wm>           Is the 32-bit name of the second general-purpose source register, encoded in the "Rm" field.

<Xd>           Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>           Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Xm>           Is the 64-bit name of the second general-purpose source register, encoded in the "Rm" field.

<shift>        Is the optional shift to be applied to the final source, defaulting to LSL and encoded in the "shift"
               field. It can have the following values:

               LSL          when shift = 00

               LSR          when shift = 01

               ASR          when shift = 10

               ROR          when shift = 11
       <amount>        For the 32-bit variant: is the shift amount, in the range 0 to 31, defaulting to 0 and encoded in the
                       "imm6" field.

                       For the 64-bit variant: is the shift amount, in the range 0 to 63, defaulting to 0 and encoded in the
                       "imm6" field.


       Operation

         bits(datasize) operand1 = X[n];
         bits(datasize) operand2 = ShiftReg(m, shift_type, shift_amount);

         if invert then operand2 = NOT(operand2);

         case op of
              when LogicalOp_AND result = operand1 AND operand2;
              when LogicalOp_ORR result = operand1 OR       operand2;
              when LogicalOp_EOR result = operand1 EOR operand2;

         if setflags then
              PSTATE.<N,Z,C,V> = result<datasize-1>:IsZeroBit(result):'00';

         X[d] = result;


platform: ARM
mnem: EOR
description:
Bitwise exclusive OR (immediate): Rd = Rn EOR imm       (C6.6.64)




  31 30 29 28 27 26 25 24 23 22 21                16 15             10 9             5 4              0
  sf 1 0 1 0 0 1 0 0 N                  immr               imms               Rn               Rd
     opc


32-bit variant

Applies when sf = 0 && N = 0.

EOR <Wd|WSP>, <Wn>, #<imm>


64-bit variant

Applies when sf = 1.

EOR <Xd|SP>, <Xn>, #<imm>


Decode for all variants of this encoding

 integer d = UInt(Rd);
 integer n = UInt(Rn);
 integer datasize = if sf == '1' then 64 else 32;
 boolean setflags;
 LogicalOp op;
 case opc of
     when '00' op = LogicalOp_AND; setflags = FALSE;
     when '01' op = LogicalOp_ORR; setflags = FALSE;
     when '10' op = LogicalOp_EOR; setflags = FALSE;
     when '11' op = LogicalOp_AND; setflags = TRUE;

 bits(datasize) imm;
 if sf == '0' && N != '0' then ReservedValue();
 (imm, -) = DecodeBitMasks(N, imms, immr, TRUE);


Assembler symbols

<Wd|WSP>       Is the 32-bit name of the destination general-purpose register or stack pointer, encoded in the "Rd"
               field.

<Wn>           Is the 32-bit name of the general-purpose source register, encoded in the "Rn" field.

<Xd|SP>        Is the 64-bit name of the destination general-purpose register or stack pointer, encoded in the "Rd"
               field.

<Xn>           Is the 64-bit name of the general-purpose source register, encoded in the "Rn" field.

<imm>          Is the bitmask immediate, encoded in "N:imms:immr".


Operation

 bits(datasize) result;
 bits(datasize) operand1 = X[n];
 bits(datasize) operand2 = imm;

 case op of
     when LogicalOp_AND result = operand1 AND operand2;
     when LogicalOp_ORR result = operand1 OR      operand2;
     when LogicalOp_EOR result = operand1 EOR operand2;

         if setflags then
              PSTATE.<N,Z,C,V> = result<datasize-1>:IsZeroBit(result):'00';

         if d == 31 && !setflags then
              SP[] = result;
         else
              X[d] = result;


platform: ARM
mnem: ERET
description:
Exception return using current ELR and SPSR       (C6.6.66)




  31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
  1 1 0 1 0 1 1 0 1 0 0 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0




System variant

ERET


Decode for this encoding

 if PSTATE.EL == EL0 then UnallocatedEncoding();


Operation

 AArch64.ExceptionReturn(ELR[], SPSR[]);


platform: ARM
mnem: EXTR
description:
       Extract register from pair of registers       (C6.6.67)

       This instruction is used by the alias ROR (immediate). See the Alias conditions table for details of when each alias
       is preferred.




           31 30 29 28 27 26 25 24 23 22 21 20              16 15                10 9            5 4               0
           sf 0 0 1 0 0 1 1 1 N 0                   Rm                imms                Rn              Rd




       32-bit variant

       Applies when sf = 0 && N = 0 && imms = 0xxxxx.

       EXTR <Wd>, <Wn>, <Wm>, #<lsb>


       64-bit variant

       Applies when sf = 1 && N = 1.

       EXTR <Xd>, <Xn>, <Xm>, #<lsb>


       Decode for all variants of this encoding

         integer d = UInt(Rd);
         integer n = UInt(Rn);
         integer m = UInt(Rm);
         integer datasize = if sf == '1' then 64 else 32;
         integer lsb;

         if N != sf then UnallocatedEncoding();
         if sf == '0' && imms<5> == '1' then ReservedValue();
         lsb = UInt(imms);


       Alias conditions


                            Alias                      is preferred when

                            ROR (immediate)            Rn == Rm



       Assembler symbols

       <Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <Wn>            Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

       <Wm>            Is the 32-bit name of the second general-purpose source register, encoded in the "Rm" field.

       <Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <Xn>            Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

       <Xm>            Is the 64-bit name of the second general-purpose source register, encoded in the "Rm" field.

       <lsb>           For the 32-bit variant: is the least significant bit position from which to extract, in the range 0 to 31,
                       encoded in the "imms" field.

                       For the 64-bit variant: is the least significant bit position from which to extract, in the range 0 to 63,
                       encoded in the "imms" field.
Operation

 bits(datasize) result;
 bits(datasize) operand1 = X[n];
 bits(datasize) operand2 = X[m];
 bits(2*datasize) concat = operand1:operand2;

 result = concat<lsb+datasize-1:lsb>;

 X[d] = result;


platform: ARM
mnem: HINT
description:
    Hint instruction       (C6.6.68)

    This instruction is used by the aliases NOP, SEVL, SEV, WFE, WFI, and YIELD. See the Alias conditions table
    for details of when each alias is preferred.




        31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11          8 7      5 4 3 2 1 0
        1 1 0 1 0 1 0 1 0 0 0 0 0 0 1 1 0 0 1 0                            CRm        op2  1 1 1 1 1




    System variant

    HINT #<imm>


    Decode for this encoding

      SystemHintOp op;

      case CRm:op2 of
           when '0000 000' op = SystemHintOp_NOP;
           when '0000 001' op = SystemHintOp_YIELD;
           when '0000 010' op = SystemHintOp_WFE;
           when '0000 011' op = SystemHintOp_WFI;
           when '0000 100' op = SystemHintOp_SEV;
           when '0000 101' op = SystemHintOp_SEVL;
           otherwise   op = SystemHintOp_NOP;


    Alias conditions


                          Alias                  is preferred when

                          NOP                    CRm == '0000' && op2 == '000'

                          SEVL                   CRm == '0000' && op2 == '101'

                          SEV                    CRm == '0000' && op2 == '100'

                          WFE                    CRm == '0000' && op2 == '010'

                          WFI                    CRm == '0000' && op2 == '011'

                          YIELD                  CRm == '0000' && op2 == '001'



    Assembler symbols

    <imm>            Is a 7-bit unsigned immediate, in the range 0 to 127, encoded in "CRm:op2".


    Operation

      case op of
           when SystemHintOp_YIELD
                Hint_Yield();

           when SystemHintOp_WFE
                if EventRegistered() then
                    ClearEventRegister();
                else
                   if PSTATE.EL == EL0 then
            AArch64.CheckForWFxTrap(EL1, TRUE);
       if HaveEL(EL2) && !IsSecure() && PSTATE.EL IN {EL0,EL1} then
            AArch64.CheckForWFxTrap(EL2, TRUE);
       if HaveEL(EL3) && PSTATE.EL != EL3 then
            AArch64.CheckForWFxTrap(EL3, TRUE);
        WaitForEvent();

when SystemHintOp_WFI
   if !InterruptPending() then
       if PSTATE.EL == EL0 then
            AArch64.CheckForWFxTrap(EL1, FALSE);
       if HaveEL(EL2) && !IsSecure() && PSTATE.EL IN {EL0,EL1} then
            AArch64.CheckForWFxTrap(EL2, FALSE);
       if HaveEL(EL3) && PSTATE.EL != EL3 then
            AArch64.CheckForWFxTrap(EL3, FALSE);
        WaitForInterrupt();

when SystemHintOp_SEV
    SendEvent();

when SystemHintOp_SEVL
    EventRegisterSet();

otherwise // do nothing


platform: ARM
mnem: HLT
description:
External debug breakpoint       (C6.6.69)




    31 30 29 28 27 26 25 24 23 22 21 20                                              5 4 3 2 1 0
    1 1 0 1 0 1 0 0 0 1 0                                 imm16                         0 0 0 0 0




System variant

HLT #<imm>


Decode for this encoding

  if EDSCR.HDE == '0' || !HaltingAllowed() then UndefinedFault();


Assembler symbols

<imm>           Is a 16-bit unsigned immediate, in the range 0 to 65535, encoded in the "imm16" field.


Operation

  Halt(DebugHalt_HaltInstruction);


platform: ARM
mnem: HVC
description:
Generate exception targeting exception level 2       (C6.6.70)




  31 30 29 28 27 26 25 24 23 22 21 20                                              5 4 3 2 1 0
  1 1 0 1 0 1 0 0 0 0 0                                 imm16                         0 0 0 1 0




System variant

HVC #<imm>


Decode for this encoding

 bits(16) imm = imm16;


Assembler symbols

<imm>         Is a 16-bit unsigned immediate, in the range 0 to 65535, encoded in the "imm16" field.


Operation

 if !HaveEL(EL2) || PSTATE.EL == EL0 || (PSTATE.EL == EL1 && IsSecure()) then
     UnallocatedEncoding();

 hvc_enable = if HaveEL(EL3) then SCR_EL3.HCE else NOT(HCR_EL2.HCD);
 if hvc_enable == '0' then
     AArch64.UndefinedFault();
 else
     AArch64.CallHypervisor(imm);


platform: ARM
mnem: IC
description:
Instruction cache operation       (C6.6.71)

This instruction is an alias of the SYS instruction. This means that:

.       The encodings in this description are named to match the encodings of SYS.

.       The description of SYS gives the operational pseudocode for this instruction.




    31 30 29 28 27 26 25 24 23 22 21 20 19 18      16 15         12 11       8 7       5 4             0
    1 1 0 1 0 1 0 1 0 0 0 0 1                  op1      0 1 1 1        CRm        op2           Rt
                                    L                      CRn


System variant

IC <ic_op>{, <Xt>}

is equivalent to

SYS #<op1>, C7, <Cm>, #<op2>{, <Xt>}

and is the preferred disassembly when SysOp(op1,'0111',CRm,op2) == Sys_IC.


Assembler symbols

<ic_op>         Is an IC operation name, as listed for the IC system operation pages, encoded in the "op1:CRm:op2"
                field. It can have the following values:

                IALLUIS      when op1 = 000, CRm = 0001, op2 = 000

                IALLU        when op1 = 000, CRm = 0101, op2 = 000

                IVAU         when op1 = 011, CRm = 0101, op2 = 001

<op1>           Is a 3-bit unsigned immediate, in the range 0 to 7, encoded in the "op1" field.

<Cm>            Is a name 'Cm', with 'm' in the range 0 to 15, encoded in the "CRm" field.

<op2>           Is a 3-bit unsigned immediate, in the range 0 to 7, encoded in the "op2" field.

<Xt>            Is the 64-bit name of the optional general-purpose source register, defaulting to '11111', encoded in
                the "Rt" field.


Operation

The description of SYS gives the operational pseudocode for this instruction.


platform: ARM
mnem: ISB
description:
Instruction synchronization barrier       (C6.6.72)




  31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11           8 7 6 5 4 3 2 1 0
  1 1 0 1 0 1 0 1 0 0 0 0 0 0 1 1 0 0 1 1                            CRm       1 1 0 1 1 1 1 1
                                                                                   opc


System variant

ISB {<option>|#<imm>}


Decode for this encoding

 MemBarrierOp op;
 MBReqDomain domain;
 MBReqTypes types;

 case opc of
     when '00' op = MemBarrierOp_DSB;
     when '01' op = MemBarrierOp_DMB;
     when '10' op = MemBarrierOp_ISB;
     otherwise UnallocatedEncoding();

 case CRm<3:2> of
     when '00' domain = MBReqDomain_OuterShareable;
     when '01' domain = MBReqDomain_Nonshareable;
     when '10' domain = MBReqDomain_InnerShareable;
     when '11' domain = MBReqDomain_FullSystem;

 case CRm<1:0> of
     when '01' types = MBReqTypes_Reads;
     when '10' types = MBReqTypes_Writes;
     when '11' types = MBReqTypes_All;
     otherwise
          types = MBReqTypes_All;
          domain = MBReqDomain_FullSystem;


Assembler symbols

<option>       Specifies an optional limitation on the barrier operation. Values are:

               SY          Full system barrier operation, encoded as CRm = 0b1111. Can be omitted.

                All other encodings of CRm are reserved. The corresponding instructions execute as full system
               barrier operations, but must not be relied upon by software.

<imm>          Is an optional 4-bit unsigned immediate, in the range 0 to 15, defaulting to 15 and encoded in the
               "CRm" field.


Operation

 case op of
     when MemBarrierOp_DSB
          DataSynchronizationBarrier(domain, types);
     when MemBarrierOp_DMB
          DataMemoryBarrier(domain, types);
     when MemBarrierOp_ISB
          InstructionSynchronizationBarrier();


platform: ARM
mnem: LDAR
description:
      Load-Acquire Register loads a 32-bit word or 64-bit doubleword from memory, and writes it to a register. The       (C6.6.73)
      instruction also has memory ordering semantics as described in Load-Acquire, Store-Release on page B2-88. For
      information about memory accesses see Load/Store addressing modes on page C1-122.




          31 30 29 28 27 26 25 24 23 22 21 20            16 15 14            10 9             5 4            0
          1 x 0 0 1 0 0 0 1 1 0 (1) (1) (1) (1) (1) 1 (1) (1) (1) (1) (1)             Rn              Rt
          size                     o2 L o1        Rs        o0       Rt2


      32-bit variant

      Applies when size = 10.

      LDAR <Wt>, [<Xn|SP>{,#0}]


      64-bit variant

      Applies when size = 11.

      LDAR <Xt>, [<Xn|SP>{,#0}]


      Decode for all variants of this encoding

        integer n = UInt(Rn);
        integer t = UInt(Rt);
        integer t2 = UInt(Rt2); // ignored by load/store single register
        integer s = UInt(Rs);     // ignored by all loads and store-release

        if o2:o1:o0 == '100' || o2:o1:o0 == '11x' then UnallocatedEncoding();
        if o1 == '1' && size<1> == '0' then UnallocatedEncoding();

        AccType acctype = if o0 == '1' then AccType_ORDERED else AccType_ATOMIC;
        boolean excl = (o2 == '0');
        boolean pair = (o1 == '1');
        MemOp memop = if L == '1' then MemOp_LOAD else MemOp_STORE;
        integer elsize = 8 << UInt(size);
        integer regsize = if elsize == 64 then 64 else 32;
        integer datasize = if pair then elsize * 2 else elsize;


      Assembler symbols

      <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

      <Xt>             Is the 64-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

      <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.


      Operation

        bits(64) address;
        bits(datasize) data;
        constant integer dbytes = datasize DIV 8;
        boolean rt_unknown = FALSE;
        boolean rn_unknown = FALSE;

        if memop == MemOp_LOAD && pair && t == t2 then
             Constraint c = ConstrainUnpredictable();
             assert c IN {Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
             case c of
                  when Constraint_UNKNOWN     rt_unknown = TRUE;      // result is UNKNOWN
        when Constraint_UNDEF      UnallocatedEncoding();
        when Constraint_NOP        EndOfInstruction();

if memop == MemOp_STORE && excl then
   if s == t || (pair && s == t2) then
        Constraint c = ConstrainUnpredictable();
        assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
       case c of
           when Constraint_UNKNOWN    rt_unknown = TRUE;        // store UNKNOWN value
           when Constraint_NONE       rt_unknown = FALSE;       // store original value
           when Constraint_UNDEF      UnallocatedEncoding();
           when Constraint_NOP        EndOfInstruction();
   if s == n && n != 31 then
        Constraint c = ConstrainUnpredictable();
        assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
       case c of
           when Constraint_UNKNOWN    rn_unknown = TRUE;        // address is UNKNOWN
           when Constraint_NONE       rn_unknown = FALSE;       // address is original base
           when Constraint_UNDEF      UnallocatedEncoding();
           when Constraint_NOP        EndOfInstruction();

if n == 31 then
    CheckSPAlignment();
   address = SP[];
elsif rn_unknown then
   address = bits(64) UNKNOWN;
else
   address = X[n];

case memop of
   when MemOp_STORE
       if rt_unknown then
           data = bits(datasize) UNKNOWN;
       elsif pair then
           assert excl;
           bits(datasize DIV 2) el1 = X[t];
           bits(datasize DIV 2) el2 = X[t2];
           data = if BigEndian() then el1 : el2 else el2 : el1;
       else
           data = X[t];

        if excl then
           // store {release} exclusive register|pair (atomic)
           bit status = '1';
           // Check whether the Exclusive Monitors are set to include the
           // physical memory locations corresponding to virtual address
           // range [address, address+dbytes-1].
           if AArch64.ExclusiveMonitorsPass(address, dbytes) then
                // This atomic write will be rejected if it does not refer
                // to the same physical locations after address translation.
                Mem[address, dbytes, acctype] = data;
                status = ExclusiveMonitorsStatus();
            X[s] = ZeroExtend(status, 32);
        else
           // store release register (atomic)
            Mem[address, dbytes, acctype] = data;

   when MemOp_LOAD
        if excl then
           // Tell the Exclusive Monitors to record a sequence of one or more atomic
           // memory reads from virtual address range [address, address+dbytes-1].
           // The Exclusive Monitor will only be set if all the reads are from the
           // same dbytes-aligned physical address, to allow for the possibility of
           // an atomicity break if the translation is changed between reads.
            AArch64.SetExclusiveMonitors(address, dbytes);

        if pair then
           // load exclusive pair
                     assert excl;
                     if rt_unknown then
                         // ConstrainedUNPREDICTABLE case
                         X[t]   = bits(datasize) UNKNOWN;
                     elsif elsize == 32 then
                         // 32-bit load exclusive pair (atomic)
                         data = Mem[address, dbytes, acctype];
                         if BigEndian() then
                              X[t]  = data<datasize-1:elsize>;
                              X[t2] = data<elsize-1:0>;
                         else
                              X[t]  = data<elsize-1:0>;
                              X[t2] = data<datasize-1:elsize>;
                     else // elsize == 64
                         // 64-bit load exclusive pair (not atomic),
                         // but must be 128-bit aligned
                         if address != Align(address, dbytes) then
                             iswrite = FALSE;
                             secondstage = FALSE;
                             AArch64.Abort(address, AArch64.AlignmentFault(acctype, iswrite, secondstage));
                         X[t]   = Mem[address + 0, 8, acctype];
                         X[t2] = Mem[address + 8, 8, acctype];
                  else
                     // load {acquire} {exclusive} single register
                     data = Mem[address, dbytes, acctype];
                      X[t] = ZeroExtend(data, regsize);


platform: ARM
mnem: LDARB
description:
Load-Acquire Register Byte loads a byte from memory, zero-extends it and writes it to a register. The instruction       (C6.6.74)
also has memory ordering semantics as described in Load-Acquire, Store-Release on page B2-88. For information
about memory accesses see Load/Store addressing modes on page C1-122.




  31 30 29 28 27 26 25 24 23 22 21 20           16 15 14            10 9             5 4             0
   0 0 0 0 1 0 0 0 1 1 0 (1) (1) (1) (1) (1) 1 (1) (1) (1) (1) (1)           Rn              Rt
   size                   o2 L o1        Rs        o0       Rt2


No offset variant

LDARB <Wt>, [<Xn|SP>{,#0}]


Decode for this encoding

 integer n = UInt(Rn);
 integer t = UInt(Rt);
 integer t2 = UInt(Rt2); // ignored by load/store single register
 integer s = UInt(Rs);   // ignored by all loads and store-release

 if o2:o1:o0 == '100' || o2:o1:o0 == '11x' then UnallocatedEncoding();
 if o1 == '1' && size<1> == '0' then UnallocatedEncoding();

 AccType acctype = if o0 == '1' then AccType_ORDERED else AccType_ATOMIC;
 boolean excl = (o2 == '0');
 boolean pair = (o1 == '1');
 MemOp memop = if L == '1' then MemOp_LOAD else MemOp_STORE;
 integer elsize = 8 << UInt(size);
 integer regsize = if elsize == 64 then 64 else 32;
 integer datasize = if pair then elsize * 2 else elsize;


Assembler symbols

<Wt>          Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

<Xn|SP>       Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.


Operation

 bits(64) address;
 bits(datasize) data;
 constant integer dbytes = datasize DIV 8;
 boolean rt_unknown = FALSE;
 boolean rn_unknown = FALSE;

 if memop == MemOp_LOAD && pair && t == t2 then
     Constraint c = ConstrainUnpredictable();
     assert c IN {Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
     case c of
         when Constraint_UNKNOWN     rt_unknown = TRUE;      // result is UNKNOWN
         when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP         EndOfInstruction();

 if memop == MemOp_STORE && excl then
     if s == t || (pair && s == t2) then
         Constraint c = ConstrainUnpredictable();
         assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
         case c of
            when Constraint_UNKNOWN       rt_unknown = TRUE;      // store UNKNOWN value
            when Constraint_NONE          rt_unknown = FALSE;     // store original value
                      when Constraint_UNDEF      UnallocatedEncoding();
                      when Constraint_NOP         EndOfInstruction();
              if s == n && n != 31 then
                   Constraint c = ConstrainUnpredictable();
                   assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
                   case c of
                      when Constraint_UNKNOWN    rn_unknown = TRUE;        // address is UNKNOWN
                      when Constraint_NONE       rn_unknown = FALSE;       // address is original base
                      when Constraint_UNDEF      UnallocatedEncoding();
                      when Constraint_NOP         EndOfInstruction();

         if n == 31 then
              CheckSPAlignment();
              address = SP[];
         elsif rn_unknown then
              address = bits(64) UNKNOWN;
         else
              address = X[n];

         case memop of
              when MemOp_STORE
                   if rt_unknown then
                      data = bits(datasize) UNKNOWN;
                   elsif pair then
                      assert excl;
                      bits(datasize DIV 2) el1 = X[t];
                      bits(datasize DIV 2) el2 = X[t2];
                      data = if BigEndian() then el1 : el2 else el2 : el1;
                   else
                      data = X[t];

                   if excl then
                      // store {release} exclusive register|pair (atomic)
                      bit status = '1';
                      // Check whether the Exclusive Monitors are set to include the
                      // physical memory locations corresponding to virtual address
                      // range [address, address+dbytes-1].
                      if AArch64.ExclusiveMonitorsPass(address, dbytes) then
                           // This atomic write will be rejected if it does not refer
                           // to the same physical locations after address translation.
                           Mem[address, dbytes, acctype] = data;
                           status = ExclusiveMonitorsStatus();
                       X[s] = ZeroExtend(status, 32);
                   else
                      // store release register (atomic)
                       Mem[address, dbytes, acctype] = data;

              when MemOp_LOAD
                   if excl then
                      // Tell the Exclusive Monitors to record a sequence of one or more atomic
                      // memory reads from virtual address range [address, address+dbytes-1].
                      // The Exclusive Monitor will only be set if all the reads are from the
                      // same dbytes-aligned physical address, to allow for the possibility of
                      // an atomicity break if the translation is changed between reads.
                       AArch64.SetExclusiveMonitors(address, dbytes);

                   if pair then
                      // load exclusive pair
                      assert excl;
                      if rt_unknown then
                           // ConstrainedUNPREDICTABLE case
                           X[t]  = bits(datasize) UNKNOWN;
                      elsif elsize == 32 then
                           // 32-bit load exclusive pair (atomic)
                           data = Mem[address, dbytes, acctype];
                           if BigEndian() then
                               X[t]  = data<datasize-1:elsize>;
                               X[t2] = data<elsize-1:0>;
          else
               X[t]  = data<elsize-1:0>;
               X[t2] = data<datasize-1:elsize>;
      else // elsize == 64
          // 64-bit load exclusive pair (not atomic),
          // but must be 128-bit aligned
          if address != Align(address, dbytes) then
              iswrite = FALSE;
              secondstage = FALSE;
              AArch64.Abort(address, AArch64.AlignmentFault(acctype, iswrite, secondstage));
          X[t]   = Mem[address + 0, 8, acctype];
          X[t2] = Mem[address + 8, 8, acctype];
   else
      // load {acquire} {exclusive} single register
      data = Mem[address, dbytes, acctype];
       X[t] = ZeroExtend(data, regsize);


platform: ARM
mnem: LDARH
description:
      Load-Acquire Register Halfword loads a halfword from memory, zero-extends it, and writes it to a register. The       (C6.6.75)
      instruction also has memory ordering semantics as described in Load-Acquire, Store-Release on page B2-88. For
      information about memory accesses see Load/Store addressing modes on page C1-122.




          31 30 29 28 27 26 25 24 23 22 21 20            16 15 14            10 9             5 4            0
          0 1 0 0 1 0 0 0 1 1 0 (1) (1) (1) (1) (1) 1 (1) (1) (1) (1) (1)             Rn              Rt
          size                     o2 L o1        Rs        o0       Rt2


      No offset variant

      LDARH <Wt>, [<Xn|SP>{,#0}]


      Decode for this encoding

        integer n = UInt(Rn);
        integer t = UInt(Rt);
        integer t2 = UInt(Rt2); // ignored by load/store single register
        integer s = UInt(Rs);     // ignored by all loads and store-release

        if o2:o1:o0 == '100' || o2:o1:o0 == '11x' then UnallocatedEncoding();
        if o1 == '1' && size<1> == '0' then UnallocatedEncoding();

        AccType acctype = if o0 == '1' then AccType_ORDERED else AccType_ATOMIC;
        boolean excl = (o2 == '0');
        boolean pair = (o1 == '1');
        MemOp memop = if L == '1' then MemOp_LOAD else MemOp_STORE;
        integer elsize = 8 << UInt(size);
        integer regsize = if elsize == 64 then 64 else 32;
        integer datasize = if pair then elsize * 2 else elsize;


      Assembler symbols

      <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

      <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.


      Operation

        bits(64) address;
        bits(datasize) data;
        constant integer dbytes = datasize DIV 8;
        boolean rt_unknown = FALSE;
        boolean rn_unknown = FALSE;

        if memop == MemOp_LOAD && pair && t == t2 then
             Constraint c = ConstrainUnpredictable();
             assert c IN {Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
             case c of
                  when Constraint_UNKNOWN     rt_unknown = TRUE;      // result is UNKNOWN
                  when Constraint_UNDEF       UnallocatedEncoding();
                  when Constraint_NOP         EndOfInstruction();

        if memop == MemOp_STORE && excl then
             if s == t || (pair && s == t2) then
                  Constraint c = ConstrainUnpredictable();
                  assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
                  case c of
                     when Constraint_UNKNOWN      rt_unknown = TRUE;       // store UNKNOWN value
                     when Constraint_NONE         rt_unknown = FALSE;      // store original value
           when Constraint_UNDEF      UnallocatedEncoding();
           when Constraint_NOP        EndOfInstruction();
   if s == n && n != 31 then
        Constraint c = ConstrainUnpredictable();
        assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
       case c of
           when Constraint_UNKNOWN    rn_unknown = TRUE;        // address is UNKNOWN
           when Constraint_NONE       rn_unknown = FALSE;       // address is original base
           when Constraint_UNDEF      UnallocatedEncoding();
           when Constraint_NOP        EndOfInstruction();

if n == 31 then
    CheckSPAlignment();
   address = SP[];
elsif rn_unknown then
   address = bits(64) UNKNOWN;
else
   address = X[n];

case memop of
   when MemOp_STORE
       if rt_unknown then
           data = bits(datasize) UNKNOWN;
       elsif pair then
           assert excl;
           bits(datasize DIV 2) el1 = X[t];
           bits(datasize DIV 2) el2 = X[t2];
           data = if BigEndian() then el1 : el2 else el2 : el1;
       else
           data = X[t];

       if excl then
           // store {release} exclusive register|pair (atomic)
           bit status = '1';
           // Check whether the Exclusive Monitors are set to include the
           // physical memory locations corresponding to virtual address
           // range [address, address+dbytes-1].
           if AArch64.ExclusiveMonitorsPass(address, dbytes) then
               // This atomic write will be rejected if it does not refer
               // to the same physical locations after address translation.
               Mem[address, dbytes, acctype] = data;
               status = ExclusiveMonitorsStatus();
           X[s] = ZeroExtend(status, 32);
       else
           // store release register (atomic)
           Mem[address, dbytes, acctype] = data;

   when MemOp_LOAD
       if excl then
           // Tell the Exclusive Monitors to record a sequence of one or more atomic
           // memory reads from virtual address range [address, address+dbytes-1].
           // The Exclusive Monitor will only be set if all the reads are from the
           // same dbytes-aligned physical address, to allow for the possibility of
           // an atomicity break if the translation is changed between reads.
           AArch64.SetExclusiveMonitors(address, dbytes);

       if pair then
           // load exclusive pair
           assert excl;
           if rt_unknown then
               // ConstrainedUNPREDICTABLE case
               X[t]   = bits(datasize) UNKNOWN;
           elsif elsize == 32 then
               // 32-bit load exclusive pair (atomic)
               data = Mem[address, dbytes, acctype];
               if BigEndian() then
                   X[t]   = data<datasize-1:elsize>;
                   X[t2] = data<elsize-1:0>;
                         else
                              X[t]  = data<elsize-1:0>;
                              X[t2] = data<datasize-1:elsize>;
                     else // elsize == 64
                         // 64-bit load exclusive pair (not atomic),
                         // but must be 128-bit aligned
                         if address != Align(address, dbytes) then
                             iswrite = FALSE;
                             secondstage = FALSE;
                             AArch64.Abort(address, AArch64.AlignmentFault(acctype, iswrite, secondstage));
                         X[t]   = Mem[address + 0, 8, acctype];
                         X[t2] = Mem[address + 8, 8, acctype];
                  else
                     // load {acquire} {exclusive} single register
                     data = Mem[address, dbytes, acctype];
                      X[t] = ZeroExtend(data, regsize);


platform: ARM
mnem: LDAXP
description:
Load-Acquire Exclusive Pair of Registers loads two 32-bit words or two 64-bit doublewords from memory, and       (C6.6.76)
writes them to two registers. A 32-bit pair requires the address to be doubleword aligned and is single-copy atomic
at doubleword granularity. A 64-bit pair requires the address to be quadword aligned and is single-copy atomic for
each doubleword at doubleword granularity. The PE marks the physical address being accessed as an exclusive
access. This exclusive access mark is checked by Store Exclusive instructions. See Synchronization and semaphores
on page B2-103. The instruction also has memory ordering semantics as described in Load-Acquire, Store-Release
on page B2-88. For information about memory accesses see Load/Store addressing modes on page C1-122.




  31 30 29 28 27 26 25 24 23 22 21 20              16 15 14            10 9             5 4             0
   1 x 0 0 1 0 0 0 0 1 1 (1) (1) (1) (1) (1) 1                 Rt2               Rn             Rt
   size                     o2 L o1          Rs       o0


32-bit variant

Applies when size = 10.

LDAXP <Wt1>, <Wt2>, [<Xn|SP>{,#0}]


64-bit variant

Applies when size = 11.

LDAXP <Xt1>, <Xt2>, [<Xn|SP>{,#0}]


Decode for all variants of this encoding

 integer n = UInt(Rn);
 integer t = UInt(Rt);
 integer t2 = UInt(Rt2); // ignored by load/store single register
 integer s = UInt(Rs);     // ignored by all loads and store-release

 if o2:o1:o0 == '100' || o2:o1:o0 == '11x' then UnallocatedEncoding();
 if o1 == '1' && size<1> == '0' then UnallocatedEncoding();

 AccType acctype = if o0 == '1' then AccType_ORDERED else AccType_ATOMIC;
 boolean excl = (o2 == '0');
 boolean pair = (o1 == '1');
 MemOp memop = if L == '1' then MemOp_LOAD else MemOp_STORE;
 integer elsize = 8 << UInt(size);
 integer regsize = if elsize == 64 then 64 else 32;
 integer datasize = if pair then elsize * 2 else elsize;


Notes for all encodings

For information about the CONSTRAINED UNPREDICTABLE behavior of this instruction, see Appendix J1
Architectural Constraints on UNPREDICTABLE behaviors, and particularly LDAXP on page J1-5407.


Assembler symbols

<Wt1>           Is the 32-bit name of the first general-purpose register to be transferred, encoded in the "Rt" field.

<Wt2>           Is the 32-bit name of the second general-purpose register to be transferred, encoded in the "Rt2"
                field.

<Xt1>           Is the 64-bit name of the first general-purpose register to be transferred, encoded in the "Rt" field.

<Xt2>           Is the 64-bit name of the second general-purpose register to be transferred, encoded in the "Rt2"
                field.
       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.


       Operation

         bits(64) address;
         bits(datasize) data;
         constant integer dbytes = datasize DIV 8;
         boolean rt_unknown = FALSE;
         boolean rn_unknown = FALSE;

         if memop == MemOp_LOAD && pair && t == t2 then
              Constraint c = ConstrainUnpredictable();
              assert c IN {Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
              case c of
                   when Constraint_UNKNOWN     rt_unknown = TRUE;     // result is UNKNOWN
                   when Constraint_UNDEF       UnallocatedEncoding();
                   when Constraint_NOP         EndOfInstruction();

         if memop == MemOp_STORE && excl then
              if s == t || (pair && s == t2) then
                   Constraint c = ConstrainUnpredictable();
                   assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
                   case c of
                      when Constraint_UNKNOWN      rt_unknown = TRUE;      // store UNKNOWN value
                      when Constraint_NONE         rt_unknown = FALSE;     // store original value
                      when Constraint_UNDEF        UnallocatedEncoding();
                      when Constraint_NOP          EndOfInstruction();
              if s == n && n != 31 then
                   Constraint c = ConstrainUnpredictable();
                   assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
                   case c of
                      when Constraint_UNKNOWN      rn_unknown = TRUE;      // address is UNKNOWN
                      when Constraint_NONE         rn_unknown = FALSE;     // address is original base
                      when Constraint_UNDEF        UnallocatedEncoding();
                      when Constraint_NOP          EndOfInstruction();

         if n == 31 then
              CheckSPAlignment();
              address = SP[];
         elsif rn_unknown then
              address = bits(64) UNKNOWN;
         else
              address = X[n];

         case memop of
              when MemOp_STORE
                   if rt_unknown then
                      data = bits(datasize) UNKNOWN;
                   elsif pair then
                      assert excl;
                      bits(datasize DIV 2) el1 = X[t];
                      bits(datasize DIV 2) el2 = X[t2];
                      data = if BigEndian() then el1 : el2 else el2 : el1;
                   else
                      data = X[t];

                   if excl then
                      // store {release} exclusive register|pair (atomic)
                      bit status = '1';
                      // Check whether the Exclusive Monitors are set to include the
                      // physical memory locations corresponding to virtual address
                      // range [address, address+dbytes-1].
                      if AArch64.ExclusiveMonitorsPass(address, dbytes) then
                           // This atomic write will be rejected if it does not refer
                           // to the same physical locations after address translation.
                           Mem[address, dbytes, acctype] = data;
                           status = ExclusiveMonitorsStatus();
          X[s] = ZeroExtend(status, 32);
      else
          // store release register (atomic)
          Mem[address, dbytes, acctype] = data;

   when MemOp_LOAD
      if excl then
          // Tell the Exclusive Monitors to record a sequence of one or more atomic
          // memory reads from virtual address range [address, address+dbytes-1].
          // The Exclusive Monitor will only be set if all the reads are from the
          // same dbytes-aligned physical address, to allow for the possibility of
          // an atomicity break if the translation is changed between reads.
          AArch64.SetExclusiveMonitors(address, dbytes);

      if pair then
          // load exclusive pair
          assert excl;
          if rt_unknown then
              // ConstrainedUNPREDICTABLE case
              X[t]  = bits(datasize) UNKNOWN;
          elsif elsize == 32 then
              // 32-bit load exclusive pair (atomic)
              data = Mem[address, dbytes, acctype];
              if BigEndian() then
                  X[t]  = data<datasize-1:elsize>;
                  X[t2] = data<elsize-1:0>;
              else
                  X[t]  = data<elsize-1:0>;
                  X[t2] = data<datasize-1:elsize>;
          else // elsize == 64
              // 64-bit load exclusive pair (not atomic),
              // but must be 128-bit aligned
              if address != Align(address, dbytes) then
                  iswrite = FALSE;
                  secondstage = FALSE;
                  AArch64.Abort(address, AArch64.AlignmentFault(acctype, iswrite, secondstage));
              X[t]  = Mem[address + 0, 8, acctype];
              X[t2] = Mem[address + 8, 8, acctype];
      else
          // load {acquire} {exclusive} single register
          data = Mem[address, dbytes, acctype];
          X[t] = ZeroExtend(data, regsize);


platform: ARM
mnem: LDAXR
description:
      Load-Acquire Exclusive Register loads a 32-bit word or 64-bit doubleword from memory, and writes it to a register.       (C6.6.77)
      The memory access is atomic. The PE marks the physical address being accessed as an exclusive access. This
      exclusive access mark is checked by Store Exclusive instructions. See Synchronization and semaphores on
      page B2-103. The instruction also has memory ordering semantics as described in Load-Acquire, Store-Release on
      page B2-88. For information about memory accesses see Load/Store addressing modes on page C1-122.




          31 30 29 28 27 26 25 24 23 22 21 20           16 15 14            10 9             5 4            0
          1 x 0 0 1 0 0 0 0 1 0 (1) (1) (1) (1) (1) 1 (1) (1) (1) (1) (1)            Rn              Rt
          size                    o2 L o1        Rs        o0       Rt2


      32-bit variant

      Applies when size = 10.

      LDAXR <Wt>, [<Xn|SP>{,#0}]


      64-bit variant

      Applies when size = 11.

      LDAXR <Xt>, [<Xn|SP>{,#0}]


      Decode for all variants of this encoding

        integer n = UInt(Rn);
        integer t = UInt(Rt);
        integer t2 = UInt(Rt2); // ignored by load/store single register
        integer s = UInt(Rs);    // ignored by all loads and store-release

        if o2:o1:o0 == '100' || o2:o1:o0 == '11x' then UnallocatedEncoding();
        if o1 == '1' && size<1> == '0' then UnallocatedEncoding();

        AccType acctype = if o0 == '1' then AccType_ORDERED else AccType_ATOMIC;
        boolean excl = (o2 == '0');
        boolean pair = (o1 == '1');
        MemOp memop = if L == '1' then MemOp_LOAD else MemOp_STORE;
        integer elsize = 8 << UInt(size);
        integer regsize = if elsize == 64 then 64 else 32;
        integer datasize = if pair then elsize * 2 else elsize;


      Assembler symbols

      <Wt>            Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

      <Xt>            Is the 64-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

      <Xn|SP>         Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.


      Operation

        bits(64) address;
        bits(datasize) data;
        constant integer dbytes = datasize DIV 8;
        boolean rt_unknown = FALSE;
        boolean rn_unknown = FALSE;

        if memop == MemOp_LOAD && pair && t == t2 then
             Constraint c = ConstrainUnpredictable();
             assert c IN {Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
   case c of
        when Constraint_UNKNOWN    rt_unknown = TRUE;      // result is UNKNOWN
        when Constraint_UNDEF      UnallocatedEncoding();
        when Constraint_NOP        EndOfInstruction();

if memop == MemOp_STORE && excl then
   if s == t || (pair && s == t2) then
        Constraint c = ConstrainUnpredictable();
        assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
       case c of
           when Constraint_UNKNOWN    rt_unknown = TRUE;        // store UNKNOWN value
           when Constraint_NONE       rt_unknown = FALSE;       // store original value
           when Constraint_UNDEF      UnallocatedEncoding();
           when Constraint_NOP        EndOfInstruction();
   if s == n && n != 31 then
        Constraint c = ConstrainUnpredictable();
        assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
       case c of
           when Constraint_UNKNOWN    rn_unknown = TRUE;        // address is UNKNOWN
           when Constraint_NONE       rn_unknown = FALSE;       // address is original base
           when Constraint_UNDEF      UnallocatedEncoding();
           when Constraint_NOP        EndOfInstruction();

if n == 31 then
    CheckSPAlignment();
   address = SP[];
elsif rn_unknown then
   address = bits(64) UNKNOWN;
else
   address = X[n];

case memop of
   when MemOp_STORE
       if rt_unknown then
           data = bits(datasize) UNKNOWN;
       elsif pair then
           assert excl;
           bits(datasize DIV 2) el1 = X[t];
           bits(datasize DIV 2) el2 = X[t2];
           data = if BigEndian() then el1 : el2 else el2 : el1;
        else
           data = X[t];

        if excl then
           // store {release} exclusive register|pair (atomic)
           bit status = '1';
           // Check whether the Exclusive Monitors are set to include the
           // physical memory locations corresponding to virtual address
           // range [address, address+dbytes-1].
           if AArch64.ExclusiveMonitorsPass(address, dbytes) then
                // This atomic write will be rejected if it does not refer
                // to the same physical locations after address translation.
                Mem[address, dbytes, acctype] = data;
                status = ExclusiveMonitorsStatus();
            X[s] = ZeroExtend(status, 32);
        else
           // store release register (atomic)
            Mem[address, dbytes, acctype] = data;

   when MemOp_LOAD
        if excl then
           // Tell the Exclusive Monitors to record a sequence of one or more atomic
           // memory reads from virtual address range [address, address+dbytes-1].
           // The Exclusive Monitor will only be set if all the reads are from the
           // same dbytes-aligned physical address, to allow for the possibility of
           // an atomicity break if the translation is changed between reads.
            AArch64.SetExclusiveMonitors(address, dbytes);
                  if pair then
                     // load exclusive pair
                     assert excl;
                     if rt_unknown then
                          // ConstrainedUNPREDICTABLE case
                          X[t]  = bits(datasize) UNKNOWN;
                     elsif elsize == 32 then
                          // 32-bit load exclusive pair (atomic)
                          data = Mem[address, dbytes, acctype];
                          if BigEndian() then
                              X[t]  = data<datasize-1:elsize>;
                              X[t2] = data<elsize-1:0>;
                          else
                              X[t]  = data<elsize-1:0>;
                              X[t2] = data<datasize-1:elsize>;
                     else // elsize == 64
                          // 64-bit load exclusive pair (not atomic),
                          // but must be 128-bit aligned
                          if address != Align(address, dbytes) then
                             iswrite = FALSE;
                             secondstage = FALSE;
                             AArch64.Abort(address, AArch64.AlignmentFault(acctype, iswrite, secondstage));
                          X[t]  = Mem[address + 0, 8, acctype];
                          X[t2] = Mem[address + 8, 8, acctype];
                  else
                     // load {acquire} {exclusive} single register
                     data = Mem[address, dbytes, acctype];
                      X[t] = ZeroExtend(data, regsize);


platform: ARM
mnem: LDAXRB
description:
Load-Acquire Exclusive Register Byte loads a byte from memory, zero-extends it and writes it to a register. The       (C6.6.78)
memory access is atomic. The PE marks the physical address being accessed as an exclusive access. This exclusive
access mark is checked by Store Exclusive instructions. See Synchronization and semaphores on page B2-103. The
instruction also has memory ordering semantics as described in Load-Acquire, Store-Release on page B2-88. For
information about memory accesses see Load/Store addressing modes on page C1-122.




  31 30 29 28 27 26 25 24 23 22 21 20             16 15 14            10 9             5 4             0
   0 0 0 0 1 0 0 0 0 1 0 (1) (1) (1) (1) (1) 1 (1) (1) (1) (1) (1)             Rn              Rt
   size                     o2 L o1        Rs        o0       Rt2


No offset variant

LDAXRB <Wt>, [<Xn|SP>{,#0}]


Decode for this encoding

 integer n = UInt(Rn);
 integer t = UInt(Rt);
 integer t2 = UInt(Rt2); // ignored by load/store single register
 integer s = UInt(Rs);     // ignored by all loads and store-release

 if o2:o1:o0 == '100' || o2:o1:o0 == '11x' then UnallocatedEncoding();
 if o1 == '1' && size<1> == '0' then UnallocatedEncoding();

 AccType acctype = if o0 == '1' then AccType_ORDERED else AccType_ATOMIC;
 boolean excl = (o2 == '0');
 boolean pair = (o1 == '1');
 MemOp memop = if L == '1' then MemOp_LOAD else MemOp_STORE;
 integer elsize = 8 << UInt(size);
 integer regsize = if elsize == 64 then 64 else 32;
 integer datasize = if pair then elsize * 2 else elsize;


Assembler symbols

<Wt>            Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

<Xn|SP>         Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.


Operation

 bits(64) address;
 bits(datasize) data;
 constant integer dbytes = datasize DIV 8;
 boolean rt_unknown = FALSE;
 boolean rn_unknown = FALSE;

 if memop == MemOp_LOAD && pair && t == t2 then
     Constraint c = ConstrainUnpredictable();
     assert c IN {Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
     case c of
          when Constraint_UNKNOWN      rt_unknown = TRUE;      // result is UNKNOWN
          when Constraint_UNDEF        UnallocatedEncoding();
          when Constraint_NOP          EndOfInstruction();

 if memop == MemOp_STORE && excl then
     if s == t || (pair && s == t2) then
          Constraint c = ConstrainUnpredictable();
          assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
          case c of
                      when Constraint_UNKNOWN    rt_unknown = TRUE;        // store UNKNOWN value
                      when Constraint_NONE       rt_unknown = FALSE;       // store original value
                      when Constraint_UNDEF      UnallocatedEncoding();
                      when Constraint_NOP         EndOfInstruction();
              if s == n && n != 31 then
                   Constraint c = ConstrainUnpredictable();
                   assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
                   case c of
                      when Constraint_UNKNOWN    rn_unknown = TRUE;        // address is UNKNOWN
                      when Constraint_NONE       rn_unknown = FALSE;       // address is original base
                      when Constraint_UNDEF      UnallocatedEncoding();
                      when Constraint_NOP         EndOfInstruction();

         if n == 31 then
              CheckSPAlignment();
              address = SP[];
         elsif rn_unknown then
              address = bits(64) UNKNOWN;
         else
              address = X[n];

         case memop of
              when MemOp_STORE
                   if rt_unknown then
                      data = bits(datasize) UNKNOWN;
                   elsif pair then
                      assert excl;
                      bits(datasize DIV 2) el1 = X[t];
                      bits(datasize DIV 2) el2 = X[t2];
                      data = if BigEndian() then el1 : el2 else el2 : el1;
                   else
                      data = X[t];

                   if excl then
                      // store {release} exclusive register|pair (atomic)
                      bit status = '1';
                      // Check whether the Exclusive Monitors are set to include the
                      // physical memory locations corresponding to virtual address
                      // range [address, address+dbytes-1].
                      if AArch64.ExclusiveMonitorsPass(address, dbytes) then
                           // This atomic write will be rejected if it does not refer
                           // to the same physical locations after address translation.
                           Mem[address, dbytes, acctype] = data;
                           status = ExclusiveMonitorsStatus();
                       X[s] = ZeroExtend(status, 32);
                   else
                      // store release register (atomic)
                       Mem[address, dbytes, acctype] = data;

              when MemOp_LOAD
                   if excl then
                      // Tell the Exclusive Monitors to record a sequence of one or more atomic
                      // memory reads from virtual address range [address, address+dbytes-1].
                      // The Exclusive Monitor will only be set if all the reads are from the
                      // same dbytes-aligned physical address, to allow for the possibility of
                      // an atomicity break if the translation is changed between reads.
                       AArch64.SetExclusiveMonitors(address, dbytes);

                   if pair then
                      // load exclusive pair
                      assert excl;
                      if rt_unknown then
                           // ConstrainedUNPREDICTABLE case
                           X[t]  = bits(datasize) UNKNOWN;
                      elsif elsize == 32 then
                           // 32-bit load exclusive pair (atomic)
                           data = Mem[address, dbytes, acctype];
                           if BigEndian() then
               X[t]  = data<datasize-1:elsize>;
               X[t2] = data<elsize-1:0>;
          else
               X[t]  = data<elsize-1:0>;
               X[t2] = data<datasize-1:elsize>;
      else // elsize == 64
          // 64-bit load exclusive pair (not atomic),
          // but must be 128-bit aligned
          if address != Align(address, dbytes) then
              iswrite = FALSE;
              secondstage = FALSE;
              AArch64.Abort(address, AArch64.AlignmentFault(acctype, iswrite, secondstage));
          X[t]   = Mem[address + 0, 8, acctype];
          X[t2] = Mem[address + 8, 8, acctype];
   else
      // load {acquire} {exclusive} single register
      data = Mem[address, dbytes, acctype];
       X[t] = ZeroExtend(data, regsize);


platform: ARM
mnem: LDAXRH
description:
      Load-Acquire Exclusive Register Halfword loads a halfword from memory, zero-extends it and writes it to a       (C6.6.79)
      register. The memory access is atomic. The PE marks the physical address being accessed as an exclusive access.
      This exclusive access mark is checked by Store Exclusive instructions. See Synchronization and semaphores on
      page B2-103. The instruction also has memory ordering semantics as described in Load-Acquire, Store-Release on
      page B2-88. For information about memory accesses see Load/Store addressing modes on page C1-122.




          31 30 29 28 27 26 25 24 23 22 21 20            16 15 14            10 9             5 4            0
          0 1 0 0 1 0 0 0 0 1 0 (1) (1) (1) (1) (1) 1 (1) (1) (1) (1) (1)             Rn              Rt
          size                     o2 L o1        Rs        o0       Rt2


      No offset variant

      LDAXRH <Wt>, [<Xn|SP>{,#0}]


      Decode for this encoding

        integer n = UInt(Rn);
        integer t = UInt(Rt);
        integer t2 = UInt(Rt2); // ignored by load/store single register
        integer s = UInt(Rs);     // ignored by all loads and store-release

        if o2:o1:o0 == '100' || o2:o1:o0 == '11x' then UnallocatedEncoding();
        if o1 == '1' && size<1> == '0' then UnallocatedEncoding();

        AccType acctype = if o0 == '1' then AccType_ORDERED else AccType_ATOMIC;
        boolean excl = (o2 == '0');
        boolean pair = (o1 == '1');
        MemOp memop = if L == '1' then MemOp_LOAD else MemOp_STORE;
        integer elsize = 8 << UInt(size);
        integer regsize = if elsize == 64 then 64 else 32;
        integer datasize = if pair then elsize * 2 else elsize;


      Assembler symbols

      <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

      <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.


      Operation

        bits(64) address;
        bits(datasize) data;
        constant integer dbytes = datasize DIV 8;
        boolean rt_unknown = FALSE;
        boolean rn_unknown = FALSE;

        if memop == MemOp_LOAD && pair && t == t2 then
             Constraint c = ConstrainUnpredictable();
             assert c IN {Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
             case c of
                  when Constraint_UNKNOWN     rt_unknown = TRUE;      // result is UNKNOWN
                  when Constraint_UNDEF       UnallocatedEncoding();
                  when Constraint_NOP         EndOfInstruction();

        if memop == MemOp_STORE && excl then
             if s == t || (pair && s == t2) then
                  Constraint c = ConstrainUnpredictable();
                  assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
                  case c of
           when Constraint_UNKNOWN    rt_unknown = TRUE;        // store UNKNOWN value
           when Constraint_NONE       rt_unknown = FALSE;       // store original value
           when Constraint_UNDEF      UnallocatedEncoding();
           when Constraint_NOP         EndOfInstruction();
   if s == n && n != 31 then
        Constraint c = ConstrainUnpredictable();
        assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
       case c of
           when Constraint_UNKNOWN    rn_unknown = TRUE;        // address is UNKNOWN
           when Constraint_NONE       rn_unknown = FALSE;       // address is original base
           when Constraint_UNDEF      UnallocatedEncoding();
           when Constraint_NOP         EndOfInstruction();

if n == 31 then
    CheckSPAlignment();
   address = SP[];
elsif rn_unknown then
   address = bits(64) UNKNOWN;
else
   address = X[n];

case memop of
   when MemOp_STORE
       if rt_unknown then
           data = bits(datasize) UNKNOWN;
       elsif pair then
           assert excl;
           bits(datasize DIV 2) el1 = X[t];
           bits(datasize DIV 2) el2 = X[t2];
           data = if BigEndian() then el1 : el2 else el2 : el1;
       else
           data = X[t];

       if excl then
           // store {release} exclusive register|pair (atomic)
           bit status = '1';
           // Check whether the Exclusive Monitors are set to include the
           // physical memory locations corresponding to virtual address
           // range [address, address+dbytes-1].
           if AArch64.ExclusiveMonitorsPass(address, dbytes) then
               // This atomic write will be rejected if it does not refer
               // to the same physical locations after address translation.
                Mem[address, dbytes, acctype] = data;
               status = ExclusiveMonitorsStatus();
           X[s] = ZeroExtend(status, 32);
       else
           // store release register (atomic)
           Mem[address, dbytes, acctype] = data;

   when MemOp_LOAD
       if excl then
           // Tell the Exclusive Monitors to record a sequence of one or more atomic
           // memory reads from virtual address range [address, address+dbytes-1].
           // The Exclusive Monitor will only be set if all the reads are from the
           // same dbytes-aligned physical address, to allow for the possibility of
           // an atomicity break if the translation is changed between reads.
           AArch64.SetExclusiveMonitors(address, dbytes);

        if pair then
           // load exclusive pair
           assert excl;
           if rt_unknown then
                // ConstrainedUNPREDICTABLE case
                X[t]  = bits(datasize) UNKNOWN;
           elsif elsize == 32 then
                // 32-bit load exclusive pair (atomic)
                data = Mem[address, dbytes, acctype];
                if BigEndian() then
                              X[t]  = data<datasize-1:elsize>;
                              X[t2] = data<elsize-1:0>;
                         else
                              X[t]  = data<elsize-1:0>;
                              X[t2] = data<datasize-1:elsize>;
                     else // elsize == 64
                         // 64-bit load exclusive pair (not atomic),
                         // but must be 128-bit aligned
                         if address != Align(address, dbytes) then
                             iswrite = FALSE;
                             secondstage = FALSE;
                             AArch64.Abort(address, AArch64.AlignmentFault(acctype, iswrite, secondstage));
                         X[t]   = Mem[address + 0, 8, acctype];
                         X[t2] = Mem[address + 8, 8, acctype];
                  else
                     // load {acquire} {exclusive} single register
                     data = Mem[address, dbytes, acctype];
                      X[t] = ZeroExtend(data, regsize);


platform: ARM
mnem: LDNP
description:
Load pair of registers, with non-temporal hint       (C6.6.80)




  31 30 29 28 27 26 25 24 23 22 21                     15 14         10 9              5 4               0
  x 0 1 0 1 0 0 0 0 1                      imm7                Rt2              Rn              Rt
  opc                          L


32-bit variant

Applies when opc = 00.

LDNP <Wt1>, <Wt2>, [<Xn|SP>{, #<imm>}]


64-bit variant

Applies when opc = 10.

LDNP <Xt1>, <Xt2>, [<Xn|SP>{, #<imm>}]


Decode for all variants of this encoding

 boolean wback   = FALSE;
 boolean postindex = FALSE;


Assembler symbols

<Wt1>          Is the 32-bit name of the first general-purpose register to be transferred, encoded in the "Rt" field.

<Wt2>          Is the 32-bit name of the second general-purpose register to be transferred, encoded in the "Rt2"
               field.

<Xt1>          Is the 64-bit name of the first general-purpose register to be transferred, encoded in the "Rt" field.

<Xt2>          Is the 64-bit name of the second general-purpose register to be transferred, encoded in the "Rt2"
               field.

<Xn|SP>        Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

<imm>          For the 32-bit variant: is the optional signed immediate byte offset, a multiple of 4 in the range -256
               to 252, defaulting to 0 and encoded in the "imm7" field as <imm>/4.

               For the 64-bit variant: is the optional signed immediate byte offset, a multiple of 8 in the range -512
               to 504, defaulting to 0 and encoded in the "imm7" field as <imm>/8.


Shared decode for all encodings

 integer n = UInt(Rn);
 integer t = UInt(Rt);
 integer t2 = UInt(Rt2);
 AccType acctype = AccType_STREAM;
 MemOp memop = if L == '1' then MemOp_LOAD else MemOp_STORE;
 if opc<0> == '1' then UnallocatedEncoding();
 integer scale = 2 + UInt(opc<1>);
 integer datasize = 8 << scale;
 bits(64) offset = LSL(SignExtend(imm7, 64), scale);
       Operation

         bits(64) address;
         bits(datasize) data1;
         bits(datasize) data2;
         constant integer dbytes = datasize DIV 8;
         boolean rt_unknown = FALSE;

         if memop == MemOp_LOAD && t == t2 then
              Constraint c = ConstrainUnpredictable();
              assert c IN {Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
              case c of
                   when Constraint_UNKNOWN    rt_unknown = TRUE;      // result is UNKNOWN
                   when Constraint_UNDEF      UnallocatedEncoding();
                   when Constraint_NOP        EndOfInstruction();

         if n == 31 then
              CheckSPAlignment();
              address = SP[];
         else
              address = X[n];

         if ! postindex then
              address = address + offset;

         case memop of
              when MemOp_STORE
                   if rt_unknown && t == n then
                      data1 = bits(datasize) UNKNOWN;
                   else
                      data1 = X[t];
                   if rt_unknown && t2 == n then
                      data2 = bits(datasize) UNKNOWN;
                   else
                      data2 = X[t2];
                   Mem[address + 0     , dbytes, acctype] = data1;
                   Mem[address + dbytes, dbytes, acctype] = data2;

              when MemOp_LOAD
                   data1 = Mem[address + 0     , dbytes, acctype];
                   data2 = Mem[address + dbytes, dbytes, acctype];
                   if rt_unknown then
                      data1 = bits(datasize) UNKNOWN;
                      data2 = bits(datasize) UNKNOWN;
                   X[t]  = data1;
                   X[t2] = data2;

         if wback then
              if postindex then
                   address = address + offset;
              if n == 31 then
                   SP[] = address;
              else
                   X[n] = address;


platform: ARM
mnem: LDP
description:
Load Pair of Registers calculates an address from a base register value and an immediate offset, loads two 32-bit       (C6.6.81)
words or two 64-bit doublewords from memory, and writes them to two registers. For information about memory
accesses see Load/Store addressing modes on page C1-122.


Post-index


  31 30 29 28 27 26 25 24 23 22 21                  15 14            10 9            5 4              0
  x 0 1 0 1 0 0 0 1 1                    imm7                Rt2              Rn             Rt
  opc                          L


32-bit variant

Applies when opc = 00.

LDP <Wt1>, <Wt2>, [<Xn|SP>], #<imm>


64-bit variant

Applies when opc = 10.

LDP <Xt1>, <Xt2>, [<Xn|SP>], #<imm>


Decode for all variants of this encoding

 boolean wback  = TRUE;
 boolean postindex = TRUE;


Pre-index


  31 30 29 28 27 26 25 24 23 22 21                  15 14            10 9            5 4              0
  x 0 1 0 1 0 0 1 1 1                    imm7                Rt2              Rn             Rt
  opc                          L


32-bit variant

Applies when opc = 00.

LDP <Wt1>, <Wt2>, [<Xn|SP>, #<imm>]!


64-bit variant

Applies when opc = 10.

LDP <Xt1>, <Xt2>, [<Xn|SP>, #<imm>]!


Decode for all variants of this encoding

 boolean wback  = TRUE;
 boolean postindex = FALSE;


Signed offset


  31 30 29 28 27 26 25 24 23 22 21                  15 14            10 9            5 4              0
  x 0 1 0 1 0 0 1 0 1                    imm7                Rt2              Rn             Rt
  opc                          L
       32-bit variant

       Applies when opc = 00.

       LDP <Wt1>, <Wt2>, [<Xn|SP>{, #<imm>}]


       64-bit variant

       Applies when opc = 10.

       LDP <Xt1>, <Xt2>, [<Xn|SP>{, #<imm>}]


       Decode for all variants of this encoding

         boolean wback  = FALSE;
         boolean postindex = FALSE;


       Notes for all encodings

       For information about the CONSTRAINED UNPREDICTABLE behavior of this instruction, see Appendix J1
       Architectural Constraints on UNPREDICTABLE behaviors, and particularly LDP on page J1-5406.


       Assembler symbols

       <Wt1>           Is the 32-bit name of the first general-purpose register to be transferred, encoded in the "Rt" field.

       <Wt2>           Is the 32-bit name of the second general-purpose register to be transferred, encoded in the "Rt2"
                       field.

       <Xt1>           Is the 64-bit name of the first general-purpose register to be transferred, encoded in the "Rt" field.

       <Xt2>           Is the 64-bit name of the second general-purpose register to be transferred, encoded in the "Rt2"
                       field.

       <Xn|SP>         Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <imm>           For the 32-bit post-index and 32-bit pre-index variant: is the signed immediate byte offset, a
                       multiple of 4 in the range -256 to 252, encoded in the "imm7" field as <imm>/4.

                       For the 32-bit signed offset variant: is the optional signed immediate byte offset, a multiple of 4 in
                       the range -256 to 252, defaulting to 0 and encoded in the "imm7" field as <imm>/4.

                       For the 64-bit post-index and 64-bit pre-index variant: is the signed immediate byte offset, a
                       multiple of 8 in the range -512 to 504, encoded in the "imm7" field as <imm>/8.

                       For the 64-bit signed offset variant: is the optional signed immediate byte offset, a multiple of 8 in
                       the range -512 to 504, defaulting to 0 and encoded in the "imm7" field as <imm>/8.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         integer t2 = UInt(Rt2);
         AccType acctype = AccType_NORMAL;
         MemOp memop = if L == '1' then MemOp_LOAD else MemOp_STORE;
         if L:opc<0> == '01' || opc == '11' then UnallocatedEncoding();
         boolean signed = (opc<0> != '0');
         integer scale = 2 + UInt(opc<1>);
         integer datasize = 8 << scale;
         bits(64) offset = LSL(SignExtend(imm7, 64), scale);
Operation for all encodings

 bits(64) address;
 bits(datasize) data1;
 bits(datasize) data2;
 constant integer dbytes = datasize DIV 8;
 boolean rt_unknown = FALSE;
 boolean wb_unknown = FALSE;

 if memop == MemOp_LOAD && wback && (t == n || t2 == n) && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_WBSUPPRESS wback = FALSE;          // writeback is suppressed
         when Constraint_UNKNOWN    wb_unknown = TRUE;      // writeback is UNKNOWN
         when Constraint_UNDEF      UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if memop == MemOp_STORE && wback && (t == n || t2 == n) && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_NONE       rt_unknown = FALSE;     // value stored is pre-writeback
         when Constraint_UNKNOWN    rt_unknown = TRUE;      // value stored is UNKNOWN
         when Constraint_UNDEF      UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if memop == MemOp_LOAD && t == t2 then
     Constraint c = ConstrainUnpredictable();
    assert c IN {Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_UNKNOWN    rt_unknown = TRUE;      // result is UNKNOWN
        when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
     CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
         if rt_unknown && t == n then
            data1 = bits(datasize) UNKNOWN;
         else
            data1 = X[t];
         if rt_unknown && t2 == n then
            data2 = bits(datasize) UNKNOWN;
         else
            data2 = X[t2];
         Mem[address + 0     , dbytes, acctype] = data1;
         Mem[address + dbytes, dbytes, acctype] = data2;

    when MemOp_LOAD
         data1 = Mem[address + 0     , dbytes, acctype];
         data2 = Mem[address + dbytes, dbytes, acctype];
         if rt_unknown then
            data1 = bits(datasize) UNKNOWN;
            data2 = bits(datasize) UNKNOWN;
         if signed then
             X[t]  = SignExtend(data1, 64);
             X[t2] = SignExtend(data2, 64);
         else
             X[t]  = data1;
                       X[t2] = data2;

         if wback then
              if wb_unknown then
                   address = bits(64) UNKNOWN;
              elsif postindex then
                   address = address + offset;
              if n == 31 then
                   SP[] = address;
              else
                   X[n] = address;


platform: ARM
mnem: LDPSW
description:
Load Pair of Registers Signed Word calculates an address from a base register value and an immediate offset, loads       (C6.6.82)
two 32-bit words from memory, sign-extends them, and writes them to two registers. For information about memory
accesses see Load/Store addressing modes on page C1-122.


Post-index


  31 30 29 28 27 26 25 24 23 22 21                 15 14           10 9              5 4             0
  0 1 1 0 1 0 0 0 1 1                   imm7                Rt2               Rn             Rt
  opc                         L


Post-index variant

LDPSW <Xt1>, <Xt2>, [<Xn|SP>], #<imm>


Decode for this encoding

 boolean wback   = TRUE;
 boolean postindex = TRUE;


Pre-index


  31 30 29 28 27 26 25 24 23 22 21                 15 14           10 9              5 4             0
  0 1 1 0 1 0 0 1 1 1                   imm7                Rt2               Rn             Rt
  opc                         L


Pre-index variant

LDPSW <Xt1>, <Xt2>, [<Xn|SP>, #<imm>]!


Decode for this encoding

 boolean wback   = TRUE;
 boolean postindex = FALSE;


Signed offset


  31 30 29 28 27 26 25 24 23 22 21                 15 14           10 9              5 4             0
  0 1 1 0 1 0 0 1 0 1                   imm7                Rt2               Rn             Rt
  opc                         L


Signed offset variant

LDPSW <Xt1>, <Xt2>, [<Xn|SP>{, #<imm>}]


Decode for this encoding

 boolean wback   = FALSE;
 boolean postindex = FALSE;


Notes for all encodings

For information about the CONSTRAINED UNPREDICTABLE behavior of this instruction, see Appendix J1
Architectural Constraints on UNPREDICTABLE behaviors, and particularly LDPSW on page J1-5406.
       Assembler symbols

       <Xt1>            Is the 64-bit name of the first general-purpose register to be transferred, encoded in the "Rt" field.

       <Xt2>            Is the 64-bit name of the second general-purpose register to be transferred, encoded in the "Rt2"
                        field.

       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <imm>            For the post-index and pre-index variant: is the signed immediate byte offset, a multiple of 4 in the
                        range -256 to 252, encoded in the "imm7" field as <imm>/4.

                        For the signed offset variant: is the optional signed immediate byte offset, a multiple of 4 in the
                        range -256 to 252, defaulting to 0 and encoded in the "imm7" field as <imm>/4.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         integer t2 = UInt(Rt2);
         AccType acctype = AccType_NORMAL;
         MemOp memop = if L == '1' then MemOp_LOAD else MemOp_STORE;
         if L:opc<0> == '01' || opc == '11' then UnallocatedEncoding();
         boolean signed = (opc<0> != '0');
         integer scale = 2 + UInt(opc<1>);
         integer datasize = 8 << scale;
         bits(64) offset = LSL(SignExtend(imm7, 64), scale);


       Operation for all encodings

         bits(64) address;
         bits(datasize) data1;
         bits(datasize) data2;
         constant integer dbytes = datasize DIV 8;
         boolean rt_unknown = FALSE;
         boolean wb_unknown = FALSE;

         if memop == MemOp_LOAD && wback && (t == n || t2 == n) && n != 31 then
              c = ConstrainUnpredictable();
              assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
              case c of
                   when Constraint_WBSUPPRESS wback = FALSE;             // writeback is suppressed
                   when Constraint_UNKNOWN     wb_unknown = TRUE;        // writeback is UNKNOWN
                   when Constraint_UNDEF       UnallocatedEncoding();
                   when Constraint_NOP         EndOfInstruction();

         if memop == MemOp_STORE && wback && (t == n || t2 == n) && n != 31 then
              c = ConstrainUnpredictable();
              assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
              case c of
                   when Constraint_NONE        rt_unknown = FALSE;       // value stored is pre-writeback
                   when Constraint_UNKNOWN     rt_unknown = TRUE;        // value stored is UNKNOWN
                   when Constraint_UNDEF       UnallocatedEncoding();
                   when Constraint_NOP         EndOfInstruction();

         if memop == MemOp_LOAD && t == t2 then
              Constraint c = ConstrainUnpredictable();
              assert c IN {Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
              case c of
                   when Constraint_UNKNOWN     rt_unknown = TRUE;        // result is UNKNOWN
                   when Constraint_UNDEF       UnallocatedEncoding();
                   when Constraint_NOP         EndOfInstruction();

         if n == 31 then
              CheckSPAlignment();
              address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown && t == n then
            data1 = bits(datasize) UNKNOWN;
        else
            data1 = X[t];
        if rt_unknown && t2 == n then
            data2 = bits(datasize) UNKNOWN;
        else
            data2 = X[t2];
         Mem[address + 0     , dbytes, acctype] = data1;
         Mem[address + dbytes, dbytes, acctype] = data2;

    when MemOp_LOAD
        data1 = Mem[address + 0      , dbytes, acctype];
        data2 = Mem[address + dbytes, dbytes, acctype];
        if rt_unknown then
            data1 = bits(datasize) UNKNOWN;
            data2 = bits(datasize) UNKNOWN;
        if signed then
             X[t]  = SignExtend(data1, 64);
             X[t2] = SignExtend(data2, 64);
        else
             X[t]  = data1;
             X[t2] = data2;

 if wback then
    if wb_unknown then
        address = bits(64) UNKNOWN;
    elsif postindex then
        address = address + offset;
    if n == 31 then
         SP[] = address;
    else
         X[n] = address;


platform: ARM
mnem: LDR
description:
       Load Register (immediate) calculates an address from a base register value and an immediate offset, loads a 32-bit       (C6.6.83)
       word or 64-bit doubleword from memory, and writes it to a register. For information about memory accesses see
       Load/Store addressing modes on page C1-122. The Unsigned offset variant scales the immediate offset value by the
       size of the value accessed before adding it to the base register value.


       Post-index


           31 30 29 28 27 26 25 24 23 22 21 20                         12 11 10 9         5 4              0
           1 x 1 1 1 0 0 0 0 1 0                        imm9               0 1      Rn             Rt
           size                    opc


       32-bit variant

       Applies when size = 10.

       LDR <Wt>, [<Xn|SP>], #<simm>


       64-bit variant

       Applies when size = 11.

       LDR <Xt>, [<Xn|SP>], #<simm>


       Decode for all variants of this encoding

         boolean wback = TRUE;
         boolean postindex = TRUE;
         integer scale = UInt(size);
         bits(64) offset = SignExtend(imm9, 64);


       Pre-index


           31 30 29 28 27 26 25 24 23 22 21 20                         12 11 10 9         5 4              0
           1 x 1 1 1 0 0 0 0 1 0                        imm9               1 1      Rn             Rt
           size                    opc


       32-bit variant

       Applies when size = 10.

       LDR <Wt>, [<Xn|SP>, #<simm>]!


       64-bit variant

       Applies when size = 11.

       LDR <Xt>, [<Xn|SP>, #<simm>]!


       Decode for all variants of this encoding

         boolean wback = TRUE;
         boolean postindex = FALSE;
         integer scale = UInt(size);
         bits(64) offset = SignExtend(imm9, 64);
Unsigned offset


  31 30 29 28 27 26 25 24 23 22 21                                   10 9              5 4             0
  1 x 1 1 1 0 0 1 0 1                             imm12                       Rn                Rt
  size                      opc


32-bit variant

Applies when size = 10.

LDR <Wt>, [<Xn|SP>{, #<pimm>}]


64-bit variant

Applies when size = 11.

LDR <Xt>, [<Xn|SP>{, #<pimm>}]


Decode for all variants of this encoding

 boolean wback = FALSE;
 boolean postindex = FALSE;
 integer scale = UInt(size);
 bits(64) offset = LSL(ZeroExtend(imm12, 64), scale);


Notes for all encodings

For information about the CONSTRAINED UNPREDICTABLE behavior of this instruction, see Appendix J1
Architectural Constraints on UNPREDICTABLE behaviors, and particularly LDR (immediate) on page J1-5404.


Assembler symbols

<Wt>           Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

<Xt>           Is the 64-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

<Xn|SP>        Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

<simm>         Is the signed immediate byte offset, in the range -256 to 255, encoded in the "imm9" field.

<pimm>         For the 32-bit variant: is the optional positive immediate byte offset, a multiple of 4 in the range 0
               to 16380, defaulting to 0 and encoded in the "imm12" field as <pimm>/4.

               For the 64-bit variant: is the optional positive immediate byte offset, a multiple of 8 in the range 0
               to 32760, defaulting to 0 and encoded in the "imm12" field as <pimm>/8.


Shared decode for all encodings

 integer n = UInt(Rn);
 integer t = UInt(Rt);
 AccType acctype = AccType_NORMAL;
 MemOp memop;
 boolean signed;
 integer regsize;

 if opc<1> == '0' then
     // store or zero-extending load
     memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
     regsize = if size == '11' then 64 else 32;
     signed = FALSE;
 else
     if size == '11' then
         UnallocatedEncoding();
              else
                   // sign-extending load
                   memop = MemOp_LOAD;
                   if size == '10' && opc<0> == '1' then UnallocatedEncoding();
                   regsize = if opc<0> == '1' then 32 else 64;
                   signed = TRUE;

         integer datasize = 8 << scale;


       Operation for all encodings

         bits(64) address;
         bits(datasize) data;
         boolean wb_unknown = FALSE;
         boolean rt_unknown = FALSE;

         if memop == MemOp_LOAD && wback && n == t && n != 31 then
              c = ConstrainUnpredictable();
              assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
              case c of
                   when Constraint_WBSUPPRESS wback = FALSE;         // writeback is suppressed
                   when Constraint_UNKNOWN    wb_unknown = TRUE;     // writeback is UNKNOWN
                   when Constraint_UNDEF      UnallocatedEncoding();
                   when Constraint_NOP        EndOfInstruction();

         if memop == MemOp_STORE && wback && n == t && n != 31 then
              c = ConstrainUnpredictable();
              assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
              case c of
                   when Constraint_NONE       rt_unknown = FALSE;    // value stored is original value
                   when Constraint_UNKNOWN    rt_unknown = TRUE;     // value stored is UNKNOWN
                   when Constraint_UNDEF      UnallocatedEncoding();
                   when Constraint_NOP        EndOfInstruction();

         if n == 31 then
              if memop != MemOp_PREFETCH then CheckSPAlignment();
              address = SP[];
         else
              address = X[n];

         if ! postindex then
              address = address + offset;

         case memop of
              when MemOp_STORE
                   if rt_unknown then
                      data = bits(datasize) UNKNOWN;
                   else
                      data = X[t];
                   Mem[address, datasize DIV 8, acctype] = data;

              when MemOp_LOAD
                   data = Mem[address, datasize DIV 8, acctype];
                   if signed then
                       X[t] = SignExtend(data, regsize);
                   else
                       X[t] = ZeroExtend(data, regsize);

              when MemOp_PREFETCH
                   Prefetch(address, t<4:0>);

         if wback then
              if wb_unknown then
                   address = bits(64) UNKNOWN;
              elsif postindex then
                   address = address + offset;
              if n == 31 then
       SP[] = address;
   else
       X[n] = address;


platform: ARM
mnem: LDRB
description:
Load Register Byte (immediate) calculates an address from a base register value and an immediate offset, loads a       (C6.6.86)
byte from memory, zero-extends it, and writes it to a register. For information about memory accesses see
Load/Store addressing modes on page C1-122.


Post-index


  31 30 29 28 27 26 25 24 23 22 21 20                           12 11 10 9            5 4             0
  0 0 1 1 1 0 0 0 0 1 0                        imm9                 0 1        Rn            Rt
  size                    opc


Post-index variant

LDRB <Wt>, [<Xn|SP>], #<simm>


Decode for this encoding

 boolean wback = TRUE;
 boolean postindex = TRUE;
 integer scale = UInt(size);
 bits(64) offset = SignExtend(imm9, 64);


Pre-index


  31 30 29 28 27 26 25 24 23 22 21 20                           12 11 10 9            5 4             0
  0 0 1 1 1 0 0 0 0 1 0                        imm9                 1 1        Rn            Rt
  size                    opc


Pre-index variant

LDRB <Wt>, [<Xn|SP>, #<simm>]!


Decode for this encoding

 boolean wback = TRUE;
 boolean postindex = FALSE;
 integer scale = UInt(size);
 bits(64) offset = SignExtend(imm9, 64);


Unsigned offset


  31 30 29 28 27 26 25 24 23 22 21                                    10 9            5 4             0
  0 0 1 1 1 0 0 1 0 1                            imm12                         Rn            Rt
  size                    opc


Unsigned offset variant

LDRB <Wt>, [<Xn|SP>{, #<pimm>}]


Decode for this encoding

 boolean wback = FALSE;
 boolean postindex = FALSE;
 integer scale = UInt(size);
 bits(64) offset = LSL(ZeroExtend(imm12, 64), scale);
       Notes for all encodings

       For information about the CONSTRAINED UNPREDICTABLE behavior of this instruction, see Appendix J1
       Architectural Constraints on UNPREDICTABLE behaviors, and particularly LDRB (immediate) on page J1-5404.


       Assembler symbols

       <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <simm>           Is the signed immediate byte offset, in the range -256 to 255, encoded in the "imm9" field.

       <pimm>           Is the optional positive immediate byte offset, in the range 0 to 4095, defaulting to 0 and encoded
                        in the "imm12" field.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         AccType acctype = AccType_NORMAL;
         MemOp memop;
         boolean signed;
         integer regsize;

         if opc<1> == '0' then
              // store or zero-extending load
              memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
              regsize = if size == '11' then 64 else 32;
              signed = FALSE;
         else
              if size == '11' then
                   UnallocatedEncoding();
              else
                   // sign-extending load
                   memop = MemOp_LOAD;
                   if size == '10' && opc<0> == '1' then UnallocatedEncoding();
                   regsize = if opc<0> == '1' then 32 else 64;
                   signed = TRUE;

         integer datasize = 8 << scale;


       Operation for all encodings

         bits(64) address;
         bits(datasize) data;
         boolean wb_unknown = FALSE;
         boolean rt_unknown = FALSE;

         if memop == MemOp_LOAD && wback && n == t && n != 31 then
              c = ConstrainUnpredictable();
              assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
              case c of
                   when Constraint_WBSUPPRESS wback = FALSE;           // writeback is suppressed
                   when Constraint_UNKNOWN      wb_unknown = TRUE;     // writeback is UNKNOWN
                   when Constraint_UNDEF        UnallocatedEncoding();
                   when Constraint_NOP          EndOfInstruction();

         if memop == MemOp_STORE && wback && n == t && n != 31 then
              c = ConstrainUnpredictable();
              assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
              case c of
                   when Constraint_NONE         rt_unknown = FALSE;    // value stored is original value
                   when Constraint_UNKNOWN      rt_unknown = TRUE;     // value stored is UNKNOWN
                   when Constraint_UNDEF        UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
         Mem[address, datasize DIV 8, acctype] = data;

    when MemOp_LOAD
        data = Mem[address, datasize DIV 8, acctype];
        if signed then
             X[t] = SignExtend(data, regsize);
        else
             X[t] = ZeroExtend(data, regsize);

    when MemOp_PREFETCH
         Prefetch(address, t<4:0>);

 if wback then
    if wb_unknown then
        address = bits(64) UNKNOWN;
    elsif postindex then
        address = address + offset;
    if n == 31 then
         SP[] = address;
    else
         X[n] = address;


platform: ARM
mnem: LDRH
description:
Load Register Halfword (immediate) calculates an address from a base register value and an immediate offset, loads       (C6.6.88)
a halfword from memory, zero-extends it, and writes it to a register. For information about memory accesses see
Load/Store addressing modes on page C1-122.


Post-index


  31 30 29 28 27 26 25 24 23 22 21 20                         12 11 10 9              5 4             0
  0 1 1 1 1 0 0 0 0 1 0                       imm9                0 1          Rn            Rt
   size                   opc


Post-index variant

LDRH <Wt>, [<Xn|SP>], #<simm>


Decode for this encoding

 boolean wback = TRUE;
 boolean postindex = TRUE;
 integer scale = UInt(size);
 bits(64) offset = SignExtend(imm9, 64);


Pre-index


  31 30 29 28 27 26 25 24 23 22 21 20                         12 11 10 9              5 4             0
  0 1 1 1 1 0 0 0 0 1 0                       imm9                1 1          Rn            Rt
   size                   opc


Pre-index variant

LDRH <Wt>, [<Xn|SP>, #<simm>]!


Decode for this encoding

 boolean wback = TRUE;
 boolean postindex = FALSE;
 integer scale = UInt(size);
 bits(64) offset = SignExtend(imm9, 64);


Unsigned offset


  31 30 29 28 27 26 25 24 23 22 21                                    10 9            5 4             0
  0 1 1 1 1 0 0 1 0 1                          imm12                           Rn            Rt
   size                   opc


Unsigned offset variant

LDRH <Wt>, [<Xn|SP>{, #<pimm>}]


Decode for this encoding

 boolean wback = FALSE;
 boolean postindex = FALSE;
 integer scale = UInt(size);
 bits(64) offset = LSL(ZeroExtend(imm12, 64), scale);
       Notes for all encodings

       For information about the CONSTRAINED UNPREDICTABLE behavior of this instruction, see Appendix J1
       Architectural Constraints on UNPREDICTABLE behaviors, and particularly LDRH (immediate) on page J1-5405.


       Assembler symbols

       <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <simm>           Is the signed immediate byte offset, in the range -256 to 255, encoded in the "imm9" field.

       <pimm>           Is the optional positive immediate byte offset, a multiple of 2 in the range 0 to 8190, defaulting to 0
                        and encoded in the "imm12" field as <pimm>/2.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         AccType acctype = AccType_NORMAL;
         MemOp memop;
         boolean signed;
         integer regsize;

         if opc<1> == '0' then
              // store or zero-extending load
              memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
              regsize = if size == '11' then 64 else 32;
              signed = FALSE;
         else
              if size == '11' then
                   UnallocatedEncoding();
              else
                   // sign-extending load
                   memop = MemOp_LOAD;
                   if size == '10' && opc<0> == '1' then UnallocatedEncoding();
                   regsize = if opc<0> == '1' then 32 else 64;
                   signed = TRUE;

         integer datasize = 8 << scale;


       Operation for all encodings

         bits(64) address;
         bits(datasize) data;
         boolean wb_unknown = FALSE;
         boolean rt_unknown = FALSE;

         if memop == MemOp_LOAD && wback && n == t && n != 31 then
              c = ConstrainUnpredictable();
              assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
              case c of
                   when Constraint_WBSUPPRESS wback = FALSE;           // writeback is suppressed
                   when Constraint_UNKNOWN      wb_unknown = TRUE;     // writeback is UNKNOWN
                   when Constraint_UNDEF        UnallocatedEncoding();
                   when Constraint_NOP          EndOfInstruction();

         if memop == MemOp_STORE && wback && n == t && n != 31 then
              c = ConstrainUnpredictable();
              assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
              case c of
                   when Constraint_NONE         rt_unknown = FALSE;    // value stored is original value
                   when Constraint_UNKNOWN      rt_unknown = TRUE;     // value stored is UNKNOWN
                   when Constraint_UNDEF        UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
         Mem[address, datasize DIV 8, acctype] = data;

    when MemOp_LOAD
        data = Mem[address, datasize DIV 8, acctype];
        if signed then
             X[t] = SignExtend(data, regsize);
        else
             X[t] = ZeroExtend(data, regsize);

    when MemOp_PREFETCH
         Prefetch(address, t<4:0>);

 if wback then
    if wb_unknown then
        address = bits(64) UNKNOWN;
    elsif postindex then
        address = address + offset;
    if n == 31 then
         SP[] = address;
    else
         X[n] = address;


platform: ARM
mnem: LDRSB
description:
Load Register Signed Byte (immediate) calculates an address from a base register value and an immediate byte       (C6.6.90)
offset, loads a byte from memory, sign-extends it to either 32 or 64 bits, and writes it to a register. For information
about memory accesses see Load/Store addressing modes on page C1-122.


Post-index


  31 30 29 28 27 26 25 24 23 22 21 20                          12 11 10 9               5 4               0
  0 0 1 1 1 0 0 0 1 x 0                        imm9                0 1         Rn                 Rt
   size                      opc


32-bit variant

Applies when opc = 11.

LDRSB <Wt>, [<Xn|SP>], #<simm>


64-bit variant

Applies when opc = 10.

LDRSB <Xt>, [<Xn|SP>], #<simm>


Decode for all variants of this encoding

 boolean wback = TRUE;
 boolean postindex = TRUE;
 integer scale = UInt(size);
 bits(64) offset = SignExtend(imm9, 64);


Pre-index


  31 30 29 28 27 26 25 24 23 22 21 20                          12 11 10 9               5 4               0
  0 0 1 1 1 0 0 0 1 x 0                        imm9                1 1         Rn                 Rt
   size                      opc


32-bit variant

Applies when opc = 11.

LDRSB <Wt>, [<Xn|SP>, #<simm>]!


64-bit variant

Applies when opc = 10.

LDRSB <Xt>, [<Xn|SP>, #<simm>]!


Decode for all variants of this encoding

 boolean wback = TRUE;
 boolean postindex = FALSE;
 integer scale = UInt(size);
 bits(64) offset = SignExtend(imm9, 64);
       Unsigned offset


           31 30 29 28 27 26 25 24 23 22 21                                   10 9             5 4              0
           0 0 1 1 1 0 0 1 1 x                           imm12                          Rn              Rt
           size                      opc


       32-bit variant

       Applies when opc = 11.

       LDRSB <Wt>, [<Xn|SP>{, #<pimm>}]


       64-bit variant

       Applies when opc = 10.

       LDRSB <Xt>, [<Xn|SP>{, #<pimm>}]


       Decode for all variants of this encoding

         boolean wback = FALSE;
         boolean postindex = FALSE;
         integer scale = UInt(size);
         bits(64) offset = LSL(ZeroExtend(imm12, 64), scale);


       Notes for all encodings

       For information about the CONSTRAINED UNPREDICTABLE behavior of this instruction, see Appendix J1
       Architectural Constraints on UNPREDICTABLE behaviors, and particularly LDRSB (immediate) on page J1-5405.


       Assembler symbols

       <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xt>             Is the 64-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <simm>           Is the signed immediate byte offset, in the range -256 to 255, encoded in the "imm9" field.

       <pimm>           Is the optional positive immediate byte offset, in the range 0 to 4095, defaulting to 0 and encoded
                        in the "imm12" field.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         AccType acctype = AccType_NORMAL;
         MemOp memop;
         boolean signed;
         integer regsize;

         if opc<1> == '0' then
              // store or zero-extending load
              memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
              regsize = if size == '11' then 64 else 32;
              signed = FALSE;
         else
              if size == '11' then
                   UnallocatedEncoding();
              else
                   // sign-extending load
                   memop = MemOp_LOAD;
         if size == '10' && opc<0> == '1' then UnallocatedEncoding();
         regsize = if opc<0> == '1' then 32 else 64;
         signed = TRUE;

 integer datasize = 8 << scale;


Operation for all encodings

 bits(64) address;
 bits(datasize) data;
 boolean wb_unknown = FALSE;
 boolean rt_unknown = FALSE;

 if memop == MemOp_LOAD && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_WBSUPPRESS wback = FALSE;         // writeback is suppressed
         when Constraint_UNKNOWN    wb_unknown = TRUE;     // writeback is UNKNOWN
         when Constraint_UNDEF      UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if memop == MemOp_STORE && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_NONE       rt_unknown = FALSE;    // value stored is original value
         when Constraint_UNKNOWN    rt_unknown = TRUE;     // value stored is UNKNOWN
        when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
         Mem[address, datasize DIV 8, acctype] = data;

    when MemOp_LOAD
        data = Mem[address, datasize DIV 8, acctype];
        if signed then
            X[t] = SignExtend(data, regsize);
         else
             X[t] = ZeroExtend(data, regsize);

    when MemOp_PREFETCH
         Prefetch(address, t<4:0>);

 if wback then
    if wb_unknown then
         address = bits(64) UNKNOWN;
    elsif postindex then
         address = address + offset;
    if n == 31 then
         SP[] = address;
    else
         X[n] = address;


platform: ARM
mnem: LDRSH
description:
Load Register Signed Halfword (immediate) calculates an address from a base register value and an immediate       (C6.6.92)
offset, loads a halfword from memory, sign-extends it, and writes it to a register. For information about memory
accesses see Load/Store addressing modes on page C1-122.


Post-index


  31 30 29 28 27 26 25 24 23 22 21 20                         12 11 10 9               5 4             0
  0 1 1 1 1 0 0 0 1 x 0                       imm9                 0 1         Rn               Rt
   size                      opc


32-bit variant

Applies when opc = 11.

LDRSH <Wt>, [<Xn|SP>], #<simm>


64-bit variant

Applies when opc = 10.

LDRSH <Xt>, [<Xn|SP>], #<simm>


Decode for all variants of this encoding

 boolean wback = TRUE;
 boolean postindex = TRUE;
 integer scale = UInt(size);
 bits(64) offset = SignExtend(imm9, 64);


Pre-index


  31 30 29 28 27 26 25 24 23 22 21 20                         12 11 10 9               5 4             0
  0 1 1 1 1 0 0 0 1 x 0                       imm9                 1 1         Rn               Rt
   size                      opc


32-bit variant

Applies when opc = 11.

LDRSH <Wt>, [<Xn|SP>, #<simm>]!


64-bit variant

Applies when opc = 10.

LDRSH <Xt>, [<Xn|SP>, #<simm>]!


Decode for all variants of this encoding

 boolean wback = TRUE;
 boolean postindex = FALSE;
 integer scale = UInt(size);
 bits(64) offset = SignExtend(imm9, 64);
       Unsigned offset


           31 30 29 28 27 26 25 24 23 22 21                                   10 9               5 4            0
           0 1 1 1 1 0 0 1 1 x                           imm12                           Rn               Rt
           size                      opc


       32-bit variant

       Applies when opc = 11.

       LDRSH <Wt>, [<Xn|SP>{, #<pimm>}]


       64-bit variant

       Applies when opc = 10.

       LDRSH <Xt>, [<Xn|SP>{, #<pimm>}]


       Decode for all variants of this encoding

         boolean wback = FALSE;
         boolean postindex = FALSE;
         integer scale = UInt(size);
         bits(64) offset = LSL(ZeroExtend(imm12, 64), scale);


       Notes for all encodings

       For information about the CONSTRAINED UNPREDICTABLE behavior of this instruction, see Appendix J1
       Architectural Constraints on UNPREDICTABLE behaviors, and particularly LDRSH (immediate) on page J1-5405.


       Assembler symbols

       <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xt>             Is the 64-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <simm>           Is the signed immediate byte offset, in the range -256 to 255, encoded in the "imm9" field.

       <pimm>           Is the optional positive immediate byte offset, a multiple of 2 in the range 0 to 8190, defaulting to 0
                        and encoded in the "imm12" field as <pimm>/2.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         AccType acctype = AccType_NORMAL;
         MemOp memop;
         boolean signed;
         integer regsize;

         if opc<1> == '0' then
              // store or zero-extending load
              memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
              regsize = if size == '11' then 64 else 32;
              signed = FALSE;
         else
              if size == '11' then
                   UnallocatedEncoding();
              else
                   // sign-extending load
                   memop = MemOp_LOAD;
         if size == '10' && opc<0> == '1' then UnallocatedEncoding();
         regsize = if opc<0> == '1' then 32 else 64;
         signed = TRUE;

 integer datasize = 8 << scale;


Operation for all encodings

 bits(64) address;
 bits(datasize) data;
 boolean wb_unknown = FALSE;
 boolean rt_unknown = FALSE;

 if memop == MemOp_LOAD && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_WBSUPPRESS wback = FALSE;         // writeback is suppressed
         when Constraint_UNKNOWN    wb_unknown = TRUE;     // writeback is UNKNOWN
         when Constraint_UNDEF      UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if memop == MemOp_STORE && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_NONE       rt_unknown = FALSE;    // value stored is original value
         when Constraint_UNKNOWN    rt_unknown = TRUE;     // value stored is UNKNOWN
        when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
         Mem[address, datasize DIV 8, acctype] = data;

    when MemOp_LOAD
        data = Mem[address, datasize DIV 8, acctype];
        if signed then
            X[t] = SignExtend(data, regsize);
         else
             X[t] = ZeroExtend(data, regsize);

    when MemOp_PREFETCH
         Prefetch(address, t<4:0>);

 if wback then
    if wb_unknown then
         address = bits(64) UNKNOWN;
    elsif postindex then
         address = address + offset;
    if n == 31 then
         SP[] = address;
    else
         X[n] = address;


platform: ARM
mnem: LDRSW
description:
Load Register Signed Word (immediate) calculates an address from a base register value and an immediate offset,       (C6.6.94)
loads a word from memory, sign-extends it, and writes it to a register. For information about memory accesses see
Load/Store addressing modes on page C1-122.


Post-index


  31 30 29 28 27 26 25 24 23 22 21 20                          12 11 10 9             5 4              0
  1 0 1 1 1 0 0 0 1 0 0                       imm9                0 1          Rn             Rt
  size                    opc


Post-index variant

LDRSW <Xt>, [<Xn|SP>], #<simm>


Decode for this encoding

 boolean wback = TRUE;
 boolean postindex = TRUE;
 integer scale = UInt(size);
 bits(64) offset = SignExtend(imm9, 64);


Pre-index


  31 30 29 28 27 26 25 24 23 22 21 20                          12 11 10 9             5 4              0
  1 0 1 1 1 0 0 0 1 0 0                       imm9                1 1          Rn             Rt
  size                    opc


Pre-index variant

LDRSW <Xt>, [<Xn|SP>, #<simm>]!


Decode for this encoding

 boolean wback = TRUE;
 boolean postindex = FALSE;
 integer scale = UInt(size);
 bits(64) offset = SignExtend(imm9, 64);


Unsigned offset


  31 30 29 28 27 26 25 24 23 22 21                                   10 9             5 4              0
  1 0 1 1 1 0 0 1 1 0                          imm12                           Rn             Rt
  size                    opc


Unsigned offset variant

LDRSW <Xt>, [<Xn|SP>{, #<pimm>}]


Decode for this encoding

 boolean wback = FALSE;
 boolean postindex = FALSE;
 integer scale = UInt(size);
 bits(64) offset = LSL(ZeroExtend(imm12, 64), scale);
       Notes for all encodings

       For information about the CONSTRAINED UNPREDICTABLE behavior of this instruction, see Appendix J1
       Architectural Constraints on UNPREDICTABLE behaviors, and particularly LDRSW (immediate) on page J1-5406.


       Assembler symbols

       <Xt>             Is the 64-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <simm>           Is the signed immediate byte offset, in the range -256 to 255, encoded in the "imm9" field.

       <pimm>           Is the optional positive immediate byte offset, a multiple of 4 in the range 0 to 16380, defaulting to
                        0 and encoded in the "imm12" field as <pimm>/4.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         AccType acctype = AccType_NORMAL;
         MemOp memop;
         boolean signed;
         integer regsize;

         if opc<1> == '0' then
              // store or zero-extending load
              memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
              regsize = if size == '11' then 64 else 32;
              signed = FALSE;
         else
              if size == '11' then
                   UnallocatedEncoding();
              else
                   // sign-extending load
                   memop = MemOp_LOAD;
                   if size == '10' && opc<0> == '1' then UnallocatedEncoding();
                   regsize = if opc<0> == '1' then 32 else 64;
                   signed = TRUE;

         integer datasize = 8 << scale;


       Operation for all encodings

         bits(64) address;
         bits(datasize) data;
         boolean wb_unknown = FALSE;
         boolean rt_unknown = FALSE;

         if memop == MemOp_LOAD && wback && n == t && n != 31 then
              c = ConstrainUnpredictable();
              assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
              case c of
                   when Constraint_WBSUPPRESS wback = FALSE;           // writeback is suppressed
                   when Constraint_UNKNOWN      wb_unknown = TRUE;     // writeback is UNKNOWN
                   when Constraint_UNDEF        UnallocatedEncoding();
                   when Constraint_NOP          EndOfInstruction();

         if memop == MemOp_STORE && wback && n == t && n != 31 then
              c = ConstrainUnpredictable();
              assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
              case c of
                   when Constraint_NONE         rt_unknown = FALSE;    // value stored is original value
                   when Constraint_UNKNOWN      rt_unknown = TRUE;     // value stored is UNKNOWN
                   when Constraint_UNDEF        UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
         Mem[address, datasize DIV 8, acctype] = data;

    when MemOp_LOAD
        data = Mem[address, datasize DIV 8, acctype];
        if signed then
             X[t] = SignExtend(data, regsize);
        else
             X[t] = ZeroExtend(data, regsize);

    when MemOp_PREFETCH
         Prefetch(address, t<4:0>);

 if wback then
    if wb_unknown then
        address = bits(64) UNKNOWN;
    elsif postindex then
        address = address + offset;
    if n == 31 then
         SP[] = address;
    else
         X[n] = address;


platform: ARM
mnem: LDTR
description:
       Load Register (unprivileged) calculates an address from a base register and an immediate byte offset, loads a word       (C6.6.97)
       or doubleword from memory, zero-extends it, and writes it to a register. For information about memory accesses see
       Load/Store addressing modes on page C1-122.




           31 30 29 28 27 26 25 24 23 22 21 20                         12 11 10 9              5 4             0
           1 x 1 1 1 0 0 0 0 1 0                        imm9               1 0         Rn               Rt
           size                      opc


       32-bit variant

       Applies when size = 10.

       LDTR <Wt>, [<Xn|SP>{, #<simm>}]


       64-bit variant

       Applies when size = 11.

       LDTR <Xt>, [<Xn|SP>{, #<simm>}]


       Decode for all variants of this encoding

         boolean wback = FALSE;
         boolean postindex = FALSE;
         integer scale = UInt(size);
         bits(64) offset = SignExtend(imm9, 64);


       Assembler symbols

       <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xt>             Is the 64-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <simm>           Is the optional signed immediate byte offset, in the range -256 to 255, defaulting to 0 and encoded
                        in the "imm9" field.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         AccType acctype = AccType_UNPRIV;
         MemOp memop;
         boolean signed;
         integer regsize;

         if opc<1> == '0' then
              // store or zero-extending load
              memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
              regsize = if size == '11' then 64 else 32;
              signed = FALSE;
         else
              if size == '11' then
                   UnallocatedEncoding();
              else
                   // sign-extending load
                   memop = MemOp_LOAD;
                   if size == '10' && opc<0> == '1' then UnallocatedEncoding();
         regsize = if opc<0> == '1' then 32 else 64;
         signed = TRUE;

 integer datasize = 8 << scale;


Operation

 bits(64) address;
 bits(datasize) data;
 boolean wb_unknown = FALSE;
 boolean rt_unknown = FALSE;

 if memop == MemOp_LOAD && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_WBSUPPRESS wback = FALSE;         // writeback is suppressed
         when Constraint_UNKNOWN    wb_unknown = TRUE;     // writeback is UNKNOWN
         when Constraint_UNDEF      UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if memop == MemOp_STORE && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_NONE       rt_unknown = FALSE;    // value stored is original value
         when Constraint_UNKNOWN    rt_unknown = TRUE;     // value stored is UNKNOWN
        when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
         Mem[address, datasize DIV 8, acctype] = data;

    when MemOp_LOAD
        data = Mem[address, datasize DIV 8, acctype];
        if signed then
            X[t] = SignExtend(data, regsize);
        else
            X[t] = ZeroExtend(data, regsize);

    when MemOp_PREFETCH
         Prefetch(address, t<4:0>);

 if wback then
    if wb_unknown then
         address = bits(64) UNKNOWN;
    elsif postindex then
         address = address + offset;
    if n == 31 then
         SP[] = address;
    else
         X[n] = address;


platform: ARM
mnem: LDTRB
description:
       Load Register Byte (unprivileged) calculates an address from a base register and an immediate byte offset, loads a       (C6.6.98)
       byte from memory, zero-extends it, and writes it to a register. For information about memory accesses see
       Load/Store addressing modes on page C1-122.




           31 30 29 28 27 26 25 24 23 22 21 20                         12 11 10 9              5 4             0
           0 0 1 1 1 0 0 0 0 1 0                        imm9               1 0         Rn               Rt
           size                      opc


       Unscaled offset variant

       LDTRB <Wt>, [<Xn|SP>{, #<simm>}]


       Decode for this encoding

         boolean wback = FALSE;
         boolean postindex = FALSE;
         integer scale = UInt(size);
         bits(64) offset = SignExtend(imm9, 64);


       Assembler symbols

       <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <simm>           Is the optional signed immediate byte offset, in the range -256 to 255, defaulting to 0 and encoded
                        in the "imm9" field.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         AccType acctype = AccType_UNPRIV;
         MemOp memop;
         boolean signed;
         integer regsize;

         if opc<1> == '0' then
              // store or zero-extending load
              memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
              regsize = if size == '11' then 64 else 32;
              signed = FALSE;
         else
              if size == '11' then
                   UnallocatedEncoding();
              else
                   // sign-extending load
                   memop = MemOp_LOAD;
                   if size == '10' && opc<0> == '1' then UnallocatedEncoding();
                   regsize = if opc<0> == '1' then 32 else 64;
                   signed = TRUE;

         integer datasize = 8 << scale;
Operation

 bits(64) address;
 bits(datasize) data;
 boolean wb_unknown = FALSE;
 boolean rt_unknown = FALSE;

 if memop == MemOp_LOAD && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_WBSUPPRESS wback = FALSE;         // writeback is suppressed
         when Constraint_UNKNOWN    wb_unknown = TRUE;     // writeback is UNKNOWN
         when Constraint_UNDEF      UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if memop == MemOp_STORE && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_NONE       rt_unknown = FALSE;    // value stored is original value
         when Constraint_UNKNOWN    rt_unknown = TRUE;     // value stored is UNKNOWN
        when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
         Mem[address, datasize DIV 8, acctype] = data;

    when MemOp_LOAD
        data = Mem[address, datasize DIV 8, acctype];
        if signed then
            X[t] = SignExtend(data, regsize);
        else
             X[t] = ZeroExtend(data, regsize);

    when MemOp_PREFETCH
         Prefetch(address, t<4:0>);

 if wback then
    if wb_unknown then
         address = bits(64) UNKNOWN;
    elsif postindex then
         address = address + offset;
    if n == 31 then
         SP[] = address;
    else
         X[n] = address;


platform: ARM
mnem: LDTRH
description:
       Load Register Halfword (unprivileged) calculates an address from a base register value and an immediate offset,       (C6.6.99)
       loads a halfword from memory, zero-extends it, and writes it to a register. For information about memory accesses
       see Load/Store addressing modes on page C1-122.




           31 30 29 28 27 26 25 24 23 22 21 20                         12 11 10 9              5 4             0
           0 1 1 1 1 0 0 0 0 1 0                        imm9               1 0         Rn               Rt
           size                      opc


       Unscaled offset variant

       LDTRH <Wt>, [<Xn|SP>{, #<simm>}]


       Decode for this encoding

         boolean wback = FALSE;
         boolean postindex = FALSE;
         integer scale = UInt(size);
         bits(64) offset = SignExtend(imm9, 64);


       Assembler symbols

       <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <simm>           Is the optional signed immediate byte offset, in the range -256 to 255, defaulting to 0 and encoded
                        in the "imm9" field.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         AccType acctype = AccType_UNPRIV;
         MemOp memop;
         boolean signed;
         integer regsize;

         if opc<1> == '0' then
              // store or zero-extending load
              memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
              regsize = if size == '11' then 64 else 32;
              signed = FALSE;
         else
              if size == '11' then
                   UnallocatedEncoding();
              else
                   // sign-extending load
                   memop = MemOp_LOAD;
                   if size == '10' && opc<0> == '1' then UnallocatedEncoding();
                   regsize = if opc<0> == '1' then 32 else 64;
                   signed = TRUE;

         integer datasize = 8 << scale;
Operation

 bits(64) address;
 bits(datasize) data;
 boolean wb_unknown = FALSE;
 boolean rt_unknown = FALSE;

 if memop == MemOp_LOAD && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_WBSUPPRESS wback = FALSE;         // writeback is suppressed
         when Constraint_UNKNOWN    wb_unknown = TRUE;     // writeback is UNKNOWN
         when Constraint_UNDEF      UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if memop == MemOp_STORE && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_NONE       rt_unknown = FALSE;    // value stored is original value
         when Constraint_UNKNOWN    rt_unknown = TRUE;     // value stored is UNKNOWN
        when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
         Mem[address, datasize DIV 8, acctype] = data;

    when MemOp_LOAD
        data = Mem[address, datasize DIV 8, acctype];
        if signed then
            X[t] = SignExtend(data, regsize);
        else
             X[t] = ZeroExtend(data, regsize);

    when MemOp_PREFETCH
         Prefetch(address, t<4:0>);

 if wback then
    if wb_unknown then
         address = bits(64) UNKNOWN;
    elsif postindex then
         address = address + offset;
    if n == 31 then
         SP[] = address;
    else
         X[n] = address;


platform: ARM
mnem: LDTRSB
description:
       Load Register Signed Byte (unprivileged) calculates an address from a base register and an immediate byte offset,       (C6.6.100)
       loads a signed byte from memory, sign-extends it, and writes it to a register. For information about memory accesses
       see Load/Store addressing modes on page C1-122.




           31 30 29 28 27 26 25 24 23 22 21 20                         12 11 10 9              5 4             0
           0 0 1 1 1 0 0 0 1 x 0                        imm9                1 0         Rn              Rt
           size                      opc


       32-bit variant

       Applies when opc = 11.

       LDTRSB <Wt>, [<Xn|SP>{, #<simm>}]


       64-bit variant

       Applies when opc = 10.

       LDTRSB <Xt>, [<Xn|SP>{, #<simm>}]


       Decode for all variants of this encoding

         boolean wback = FALSE;
         boolean postindex = FALSE;
         integer scale = UInt(size);
         bits(64) offset = SignExtend(imm9, 64);


       Assembler symbols

       <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xt>             Is the 64-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <simm>           Is the optional signed immediate byte offset, in the range -256 to 255, defaulting to 0 and encoded
                        in the "imm9" field.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         AccType acctype = AccType_UNPRIV;
         MemOp memop;
         boolean signed;
         integer regsize;

         if opc<1> == '0' then
              // store or zero-extending load
              memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
              regsize = if size == '11' then 64 else 32;
              signed = FALSE;
         else
              if size == '11' then
                   UnallocatedEncoding();
              else
                   // sign-extending load
                   memop = MemOp_LOAD;
                   if size == '10' && opc<0> == '1' then UnallocatedEncoding();
         regsize = if opc<0> == '1' then 32 else 64;
         signed = TRUE;

 integer datasize = 8 << scale;


Operation

 bits(64) address;
 bits(datasize) data;
 boolean wb_unknown = FALSE;
 boolean rt_unknown = FALSE;

 if memop == MemOp_LOAD && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_WBSUPPRESS wback = FALSE;         // writeback is suppressed
         when Constraint_UNKNOWN    wb_unknown = TRUE;     // writeback is UNKNOWN
         when Constraint_UNDEF      UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if memop == MemOp_STORE && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_NONE       rt_unknown = FALSE;    // value stored is original value
         when Constraint_UNKNOWN    rt_unknown = TRUE;     // value stored is UNKNOWN
        when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
         Mem[address, datasize DIV 8, acctype] = data;

    when MemOp_LOAD
        data = Mem[address, datasize DIV 8, acctype];
        if signed then
            X[t] = SignExtend(data, regsize);
        else
            X[t] = ZeroExtend(data, regsize);

    when MemOp_PREFETCH
         Prefetch(address, t<4:0>);

 if wback then
    if wb_unknown then
         address = bits(64) UNKNOWN;
    elsif postindex then
         address = address + offset;
    if n == 31 then
         SP[] = address;
    else
         X[n] = address;


platform: ARM
mnem: LDTRSH
description:
       Load Register Signed Halfword (unprivileged) calculates an address from a base register and an immediate offset,       (C6.6.101)
       loads a signed byte from memory, sign-extends it, and writes it to a register. For information about memory accesses
       see Load/Store addressing modes on page C1-122.




           31 30 29 28 27 26 25 24 23 22 21 20                         12 11 10 9              5 4             0
           0 1 1 1 1 0 0 0 1 x 0                        imm9                1 0         Rn              Rt
           size                      opc


       32-bit variant

       Applies when opc = 11.

       LDTRSH <Wt>, [<Xn|SP>{, #<simm>}]


       64-bit variant

       Applies when opc = 10.

       LDTRSH <Xt>, [<Xn|SP>{, #<simm>}]


       Decode for all variants of this encoding

         boolean wback = FALSE;
         boolean postindex = FALSE;
         integer scale = UInt(size);
         bits(64) offset = SignExtend(imm9, 64);


       Assembler symbols

       <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xt>             Is the 64-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <simm>           Is the optional signed immediate byte offset, in the range -256 to 255, defaulting to 0 and encoded
                        in the "imm9" field.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         AccType acctype = AccType_UNPRIV;
         MemOp memop;
         boolean signed;
         integer regsize;

         if opc<1> == '0' then
              // store or zero-extending load
              memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
              regsize = if size == '11' then 64 else 32;
              signed = FALSE;
         else
              if size == '11' then
                   UnallocatedEncoding();
              else
                   // sign-extending load
                   memop = MemOp_LOAD;
                   if size == '10' && opc<0> == '1' then UnallocatedEncoding();
         regsize = if opc<0> == '1' then 32 else 64;
         signed = TRUE;

 integer datasize = 8 << scale;


Operation

 bits(64) address;
 bits(datasize) data;
 boolean wb_unknown = FALSE;
 boolean rt_unknown = FALSE;

 if memop == MemOp_LOAD && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_WBSUPPRESS wback = FALSE;         // writeback is suppressed
         when Constraint_UNKNOWN    wb_unknown = TRUE;     // writeback is UNKNOWN
         when Constraint_UNDEF      UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if memop == MemOp_STORE && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_NONE       rt_unknown = FALSE;    // value stored is original value
         when Constraint_UNKNOWN    rt_unknown = TRUE;     // value stored is UNKNOWN
        when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
         Mem[address, datasize DIV 8, acctype] = data;

    when MemOp_LOAD
        data = Mem[address, datasize DIV 8, acctype];
        if signed then
            X[t] = SignExtend(data, regsize);
        else
            X[t] = ZeroExtend(data, regsize);

    when MemOp_PREFETCH
         Prefetch(address, t<4:0>);

 if wback then
    if wb_unknown then
         address = bits(64) UNKNOWN;
    elsif postindex then
         address = address + offset;
    if n == 31 then
         SP[] = address;
    else
         X[n] = address;


platform: ARM
mnem: LDTRSW
description:
       Load Register Signed Word (unprivileged) calculates an address from a base register and an immediate offset, loads       (C6.6.102)
       a signed byte from memory, sign-extends it, and writes it to a register. For information about memory accesses see
       Load/Store addressing modes on page C1-122.




           31 30 29 28 27 26 25 24 23 22 21 20                         12 11 10 9              5 4             0
           1 0 1 1 1 0 0 0 1 0 0                        imm9               1 0         Rn               Rt
           size                      opc


       Unscaled offset variant

       LDTRSW <Xt>, [<Xn|SP>{, #<simm>}]


       Decode for this encoding

         boolean wback = FALSE;
         boolean postindex = FALSE;
         integer scale = UInt(size);
         bits(64) offset = SignExtend(imm9, 64);


       Assembler symbols

       <Xt>             Is the 64-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <simm>           Is the optional signed immediate byte offset, in the range -256 to 255, defaulting to 0 and encoded
                        in the "imm9" field.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         AccType acctype = AccType_UNPRIV;
         MemOp memop;
         boolean signed;
         integer regsize;

         if opc<1> == '0' then
              // store or zero-extending load
              memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
              regsize = if size == '11' then 64 else 32;
              signed = FALSE;
         else
              if size == '11' then
                   UnallocatedEncoding();
              else
                   // sign-extending load
                   memop = MemOp_LOAD;
                   if size == '10' && opc<0> == '1' then UnallocatedEncoding();
                   regsize = if opc<0> == '1' then 32 else 64;
                   signed = TRUE;

         integer datasize = 8 << scale;
Operation

 bits(64) address;
 bits(datasize) data;
 boolean wb_unknown = FALSE;
 boolean rt_unknown = FALSE;

 if memop == MemOp_LOAD && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_WBSUPPRESS wback = FALSE;         // writeback is suppressed
         when Constraint_UNKNOWN    wb_unknown = TRUE;     // writeback is UNKNOWN
         when Constraint_UNDEF      UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if memop == MemOp_STORE && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_NONE       rt_unknown = FALSE;    // value stored is original value
         when Constraint_UNKNOWN    rt_unknown = TRUE;     // value stored is UNKNOWN
        when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
         Mem[address, datasize DIV 8, acctype] = data;

    when MemOp_LOAD
        data = Mem[address, datasize DIV 8, acctype];
        if signed then
            X[t] = SignExtend(data, regsize);
        else
             X[t] = ZeroExtend(data, regsize);

    when MemOp_PREFETCH
         Prefetch(address, t<4:0>);

 if wback then
    if wb_unknown then
         address = bits(64) UNKNOWN;
    elsif postindex then
         address = address + offset;
    if n == 31 then
         SP[] = address;
    else
         X[n] = address;


platform: ARM
mnem: LDUR
description:
       Load Register (unscaled) calculates an address from a base register and an immediate offset, loads a 32-bit word or       (C6.6.103)
       64-bit doubleword from memory, zero-extends it, and writes it to a register. For information about memory accesses
       see Load/Store addressing modes on page C1-122.




           31 30 29 28 27 26 25 24 23 22 21 20                         12 11 10 9              5 4             0
           1 x 1 1 1 0 0 0 0 1 0                        imm9               0 0         Rn               Rt
           size                      opc


       32-bit variant

       Applies when size = 10.

       LDUR <Wt>, [<Xn|SP>{, #<simm>}]


       64-bit variant

       Applies when size = 11.

       LDUR <Xt>, [<Xn|SP>{, #<simm>}]


       Decode for all variants of this encoding

         boolean wback = FALSE;
         boolean postindex = FALSE;
         integer scale = UInt(size);
         bits(64) offset = SignExtend(imm9, 64);


       Assembler symbols

       <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xt>             Is the 64-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <simm>           Is the optional signed immediate byte offset, in the range -256 to 255, defaulting to 0 and encoded
                        in the "imm9" field.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         AccType acctype = AccType_NORMAL;
         MemOp memop;
         boolean signed;
         integer regsize;

         if opc<1> == '0' then
              // store or zero-extending load
              memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
              regsize = if size == '11' then 64 else 32;
              signed = FALSE;
         else
              if size == '11' then
                   memop = MemOp_PREFETCH;
                   if opc<0> == '1' then UnallocatedEncoding();
              else
                   // sign-extending load
                   memop = MemOp_LOAD;
         if size == '10' && opc<0> == '1' then UnallocatedEncoding();
         regsize = if opc<0> == '1' then 32 else 64;
         signed = TRUE;

 integer datasize = 8 << scale;


Operation

 bits(64) address;
 bits(datasize) data;
 boolean wb_unknown = FALSE;
 boolean rt_unknown = FALSE;

 if memop == MemOp_LOAD && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_WBSUPPRESS wback = FALSE;         // writeback is suppressed
         when Constraint_UNKNOWN    wb_unknown = TRUE;     // writeback is UNKNOWN
         when Constraint_UNDEF      UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if memop == MemOp_STORE && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_NONE       rt_unknown = FALSE;    // value stored is original value
         when Constraint_UNKNOWN    rt_unknown = TRUE;     // value stored is UNKNOWN
        when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
         Mem[address, datasize DIV 8, acctype] = data;

    when MemOp_LOAD
        data = Mem[address, datasize DIV 8, acctype];
        if signed then
            X[t] = SignExtend(data, regsize);
         else
             X[t] = ZeroExtend(data, regsize);

    when MemOp_PREFETCH
         Prefetch(address, t<4:0>);

 if wback then
    if wb_unknown then
         address = bits(64) UNKNOWN;
    elsif postindex then
         address = address + offset;
    if n == 31 then
         SP[] = address;
    else
         X[n] = address;


platform: ARM
mnem: LDURB
description:
       Load Register Byte (unscaled) calculates an address from a base register and an immediate offset, loads a byte from       (C6.6.104)
       memory, zero-extends it, and writes it to a register. For information about memory accesses see Load/Store
       addressing modes on page C1-122.




           31 30 29 28 27 26 25 24 23 22 21 20                         12 11 10 9              5 4             0
           0 0 1 1 1 0 0 0 0 1 0                        imm9               0 0         Rn               Rt
           size                      opc


       Unscaled offset variant

       LDURB <Wt>, [<Xn|SP>{, #<simm>}]


       Decode for this encoding

         boolean wback = FALSE;
         boolean postindex = FALSE;
         integer scale = UInt(size);
         bits(64) offset = SignExtend(imm9, 64);


       Assembler symbols

       <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <simm>           Is the optional signed immediate byte offset, in the range -256 to 255, defaulting to 0 and encoded
                        in the "imm9" field.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         AccType acctype = AccType_NORMAL;
         MemOp memop;
         boolean signed;
         integer regsize;

         if opc<1> == '0' then
              // store or zero-extending load
              memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
              regsize = if size == '11' then 64 else 32;
              signed = FALSE;
         else
              if size == '11' then
                   memop = MemOp_PREFETCH;
                   if opc<0> == '1' then UnallocatedEncoding();
              else
                   // sign-extending load
                   memop = MemOp_LOAD;
                   if size == '10' && opc<0> == '1' then UnallocatedEncoding();
                   regsize = if opc<0> == '1' then 32 else 64;
                   signed = TRUE;

         integer datasize = 8 << scale;
Operation

 bits(64) address;
 bits(datasize) data;
 boolean wb_unknown = FALSE;
 boolean rt_unknown = FALSE;

 if memop == MemOp_LOAD && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_WBSUPPRESS wback = FALSE;         // writeback is suppressed
         when Constraint_UNKNOWN    wb_unknown = TRUE;     // writeback is UNKNOWN
         when Constraint_UNDEF      UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if memop == MemOp_STORE && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_NONE       rt_unknown = FALSE;    // value stored is original value
         when Constraint_UNKNOWN    rt_unknown = TRUE;     // value stored is UNKNOWN
        when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
         Mem[address, datasize DIV 8, acctype] = data;

    when MemOp_LOAD
        data = Mem[address, datasize DIV 8, acctype];
        if signed then
            X[t] = SignExtend(data, regsize);
        else
             X[t] = ZeroExtend(data, regsize);

    when MemOp_PREFETCH
         Prefetch(address, t<4:0>);

 if wback then
    if wb_unknown then
         address = bits(64) UNKNOWN;
    elsif postindex then
         address = address + offset;
    if n == 31 then
         SP[] = address;
    else
         X[n] = address;


platform: ARM
mnem: LDURH
description:
       Load Register Halfword (unscaled) calculates an address from a base register and an immediate offset, loads a       (C6.6.105)
       halfword from memory, zero-extends it, and writes it to a register. For information about memory accesses see
       Load/Store addressing modes on page C1-122.




           31 30 29 28 27 26 25 24 23 22 21 20                         12 11 10 9              5 4             0
           0 1 1 1 1 0 0 0 0 1 0                        imm9               0 0         Rn               Rt
           size                      opc


       Unscaled offset variant

       LDURH <Wt>, [<Xn|SP>{, #<simm>}]


       Decode for this encoding

         boolean wback = FALSE;
         boolean postindex = FALSE;
         integer scale = UInt(size);
         bits(64) offset = SignExtend(imm9, 64);


       Assembler symbols

       <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <simm>           Is the optional signed immediate byte offset, in the range -256 to 255, defaulting to 0 and encoded
                        in the "imm9" field.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         AccType acctype = AccType_NORMAL;
         MemOp memop;
         boolean signed;
         integer regsize;

         if opc<1> == '0' then
              // store or zero-extending load
              memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
              regsize = if size == '11' then 64 else 32;
              signed = FALSE;
         else
              if size == '11' then
                   memop = MemOp_PREFETCH;
                   if opc<0> == '1' then UnallocatedEncoding();
              else
                   // sign-extending load
                   memop = MemOp_LOAD;
                   if size == '10' && opc<0> == '1' then UnallocatedEncoding();
                   regsize = if opc<0> == '1' then 32 else 64;
                   signed = TRUE;

         integer datasize = 8 << scale;
Operation

 bits(64) address;
 bits(datasize) data;
 boolean wb_unknown = FALSE;
 boolean rt_unknown = FALSE;

 if memop == MemOp_LOAD && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_WBSUPPRESS wback = FALSE;         // writeback is suppressed
         when Constraint_UNKNOWN    wb_unknown = TRUE;     // writeback is UNKNOWN
         when Constraint_UNDEF      UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if memop == MemOp_STORE && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_NONE       rt_unknown = FALSE;    // value stored is original value
         when Constraint_UNKNOWN    rt_unknown = TRUE;     // value stored is UNKNOWN
        when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
         Mem[address, datasize DIV 8, acctype] = data;

    when MemOp_LOAD
        data = Mem[address, datasize DIV 8, acctype];
        if signed then
            X[t] = SignExtend(data, regsize);
        else
             X[t] = ZeroExtend(data, regsize);

    when MemOp_PREFETCH
         Prefetch(address, t<4:0>);

 if wback then
    if wb_unknown then
         address = bits(64) UNKNOWN;
    elsif postindex then
         address = address + offset;
    if n == 31 then
         SP[] = address;
    else
         X[n] = address;


platform: ARM
mnem: LDURSB
description:
       Load Register Signed Byte (unscaled) calculates an address from a base register and an immediate offset, loads a       (C6.6.106)
       signed byte from memory, sign-extends it, and writes it to a register. For information about memory accesses see
       Load/Store addressing modes on page C1-122.




           31 30 29 28 27 26 25 24 23 22 21 20                         12 11 10 9              5 4             0
           0 0 1 1 1 0 0 0 1 x 0                        imm9               0 0         Rn               Rt
           size                      opc


       32-bit variant

       Applies when opc = 11.

       LDURSB <Wt>, [<Xn|SP>{, #<simm>}]


       64-bit variant

       Applies when opc = 10.

       LDURSB <Xt>, [<Xn|SP>{, #<simm>}]


       Decode for all variants of this encoding

         boolean wback = FALSE;
         boolean postindex = FALSE;
         integer scale = UInt(size);
         bits(64) offset = SignExtend(imm9, 64);


       Assembler symbols

       <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xt>             Is the 64-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <simm>           Is the optional signed immediate byte offset, in the range -256 to 255, defaulting to 0 and encoded
                        in the "imm9" field.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         AccType acctype = AccType_NORMAL;
         MemOp memop;
         boolean signed;
         integer regsize;

         if opc<1> == '0' then
              // store or zero-extending load
              memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
              regsize = if size == '11' then 64 else 32;
              signed = FALSE;
         else
              if size == '11' then
                   memop = MemOp_PREFETCH;
                   if opc<0> == '1' then UnallocatedEncoding();
              else
                   // sign-extending load
                   memop = MemOp_LOAD;
         if size == '10' && opc<0> == '1' then UnallocatedEncoding();
         regsize = if opc<0> == '1' then 32 else 64;
         signed = TRUE;

 integer datasize = 8 << scale;


Operation

 bits(64) address;
 bits(datasize) data;
 boolean wb_unknown = FALSE;
 boolean rt_unknown = FALSE;

 if memop == MemOp_LOAD && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_WBSUPPRESS wback = FALSE;         // writeback is suppressed
         when Constraint_UNKNOWN    wb_unknown = TRUE;     // writeback is UNKNOWN
         when Constraint_UNDEF      UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if memop == MemOp_STORE && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_NONE       rt_unknown = FALSE;    // value stored is original value
         when Constraint_UNKNOWN    rt_unknown = TRUE;     // value stored is UNKNOWN
        when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
         Mem[address, datasize DIV 8, acctype] = data;

    when MemOp_LOAD
        data = Mem[address, datasize DIV 8, acctype];
        if signed then
            X[t] = SignExtend(data, regsize);
         else
             X[t] = ZeroExtend(data, regsize);

    when MemOp_PREFETCH
         Prefetch(address, t<4:0>);

 if wback then
    if wb_unknown then
         address = bits(64) UNKNOWN;
    elsif postindex then
         address = address + offset;
    if n == 31 then
         SP[] = address;
    else
         X[n] = address;


platform: ARM
mnem: LDURSH
description:
       Load Register Signed Halfword (unscaled) calculates an address from a base register and an immediate offset, loads       (C6.6.107)
       a signed halfword from memory, sign-extends it, and writes it to a register. For information about memory accesses
       see Load/Store addressing modes on page C1-122.




           31 30 29 28 27 26 25 24 23 22 21 20                         12 11 10 9              5 4             0
           0 1 1 1 1 0 0 0 1 x 0                        imm9               0 0         Rn               Rt
           size                      opc


       32-bit variant

       Applies when opc = 11.

       LDURSH <Wt>, [<Xn|SP>{, #<simm>}]


       64-bit variant

       Applies when opc = 10.

       LDURSH <Xt>, [<Xn|SP>{, #<simm>}]


       Decode for all variants of this encoding

         boolean wback = FALSE;
         boolean postindex = FALSE;
         integer scale = UInt(size);
         bits(64) offset = SignExtend(imm9, 64);


       Assembler symbols

       <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xt>             Is the 64-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <simm>           Is the optional signed immediate byte offset, in the range -256 to 255, defaulting to 0 and encoded
                        in the "imm9" field.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         AccType acctype = AccType_NORMAL;
         MemOp memop;
         boolean signed;
         integer regsize;

         if opc<1> == '0' then
              // store or zero-extending load
              memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
              regsize = if size == '11' then 64 else 32;
              signed = FALSE;
         else
              if size == '11' then
                   memop = MemOp_PREFETCH;
                   if opc<0> == '1' then UnallocatedEncoding();
              else
                   // sign-extending load
                   memop = MemOp_LOAD;
         if size == '10' && opc<0> == '1' then UnallocatedEncoding();
         regsize = if opc<0> == '1' then 32 else 64;
         signed = TRUE;

 integer datasize = 8 << scale;


Operation

 bits(64) address;
 bits(datasize) data;
 boolean wb_unknown = FALSE;
 boolean rt_unknown = FALSE;

 if memop == MemOp_LOAD && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_WBSUPPRESS wback = FALSE;         // writeback is suppressed
         when Constraint_UNKNOWN    wb_unknown = TRUE;     // writeback is UNKNOWN
         when Constraint_UNDEF      UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if memop == MemOp_STORE && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_NONE       rt_unknown = FALSE;    // value stored is original value
         when Constraint_UNKNOWN    rt_unknown = TRUE;     // value stored is UNKNOWN
        when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
         Mem[address, datasize DIV 8, acctype] = data;

    when MemOp_LOAD
        data = Mem[address, datasize DIV 8, acctype];
        if signed then
            X[t] = SignExtend(data, regsize);
         else
             X[t] = ZeroExtend(data, regsize);

    when MemOp_PREFETCH
         Prefetch(address, t<4:0>);

 if wback then
    if wb_unknown then
         address = bits(64) UNKNOWN;
    elsif postindex then
         address = address + offset;
    if n == 31 then
         SP[] = address;
    else
         X[n] = address;


platform: ARM
mnem: LDURSW
description:
       Load Register Signed Word (unscaled) calculates an address from a base register and an immediate offset, loads a       (C6.6.108)
       signed word from memory, sign-extends it, and writes it to a register. For information about memory accesses see
       Load/Store addressing modes on page C1-122.




           31 30 29 28 27 26 25 24 23 22 21 20                         12 11 10 9              5 4             0
           1 0 1 1 1 0 0 0 1 0 0                        imm9               0 0         Rn               Rt
           size                      opc


       Unscaled offset variant

       LDURSW <Xt>, [<Xn|SP>{, #<simm>}]


       Decode for this encoding

         boolean wback = FALSE;
         boolean postindex = FALSE;
         integer scale = UInt(size);
         bits(64) offset = SignExtend(imm9, 64);


       Assembler symbols

       <Xt>             Is the 64-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

       <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <simm>           Is the optional signed immediate byte offset, in the range -256 to 255, defaulting to 0 and encoded
                        in the "imm9" field.


       Shared decode for all encodings

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         AccType acctype = AccType_NORMAL;
         MemOp memop;
         boolean signed;
         integer regsize;

         if opc<1> == '0' then
              // store or zero-extending load
              memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
              regsize = if size == '11' then 64 else 32;
              signed = FALSE;
         else
              if size == '11' then
                   memop = MemOp_PREFETCH;
                   if opc<0> == '1' then UnallocatedEncoding();
              else
                   // sign-extending load
                   memop = MemOp_LOAD;
                   if size == '10' && opc<0> == '1' then UnallocatedEncoding();
                   regsize = if opc<0> == '1' then 32 else 64;
                   signed = TRUE;

         integer datasize = 8 << scale;
Operation

 bits(64) address;
 bits(datasize) data;
 boolean wb_unknown = FALSE;
 boolean rt_unknown = FALSE;

 if memop == MemOp_LOAD && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_WBSUPPRESS wback = FALSE;         // writeback is suppressed
         when Constraint_UNKNOWN    wb_unknown = TRUE;     // writeback is UNKNOWN
         when Constraint_UNDEF      UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if memop == MemOp_STORE && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_NONE       rt_unknown = FALSE;    // value stored is original value
         when Constraint_UNKNOWN    rt_unknown = TRUE;     // value stored is UNKNOWN
        when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
         Mem[address, datasize DIV 8, acctype] = data;

    when MemOp_LOAD
        data = Mem[address, datasize DIV 8, acctype];
        if signed then
            X[t] = SignExtend(data, regsize);
        else
             X[t] = ZeroExtend(data, regsize);

    when MemOp_PREFETCH
         Prefetch(address, t<4:0>);

 if wback then
    if wb_unknown then
         address = bits(64) UNKNOWN;
    elsif postindex then
         address = address + offset;
    if n == 31 then
         SP[] = address;
    else
         X[n] = address;


platform: ARM
mnem: LDXP
description:
       Load Exclusive Pair of Registers loads two 32-bit words or two 64-bit doublewords from memory, and writes them       (C6.6.109)
       to two registers. A 32-bit pair requires the address to be doubleword aligned and is single-copy atomic at
       doubleword granularity. A 64-bit pair requires the address to be quadword aligned and is single-copy atomic for
       each doubleword at doubleword granularity. The PE marks the physical address being accessed as an exclusive
       access. This exclusive access mark is checked by Store Exclusive instructions. See Synchronization and semaphores
       on page B2-103. For information about memory accesses see Load/Store addressing modes on page C1-122.




           31 30 29 28 27 26 25 24 23 22 21 20            16 15 14           10 9              5 4             0
           1 x 0 0 1 0 0 0 0 1 1 (1) (1) (1) (1) (1) 0                Rt2               Rn             Rt
           size                    o2 L o1          Rs        o0


       32-bit variant

       Applies when size = 10.

       LDXP <Wt1>, <Wt2>, [<Xn|SP>{,#0}]


       64-bit variant

       Applies when size = 11.

       LDXP <Xt1>, <Xt2>, [<Xn|SP>{,#0}]


       Decode for all variants of this encoding

         integer n = UInt(Rn);
         integer t = UInt(Rt);
         integer t2 = UInt(Rt2); // ignored by load/store single register
         integer s = UInt(Rs);     // ignored by all loads and store-release

         if o2:o1:o0 == '100' || o2:o1:o0 == '11x' then UnallocatedEncoding();
         if o1 == '1' && size<1> == '0' then UnallocatedEncoding();

         AccType acctype = if o0 == '1' then AccType_ORDERED else AccType_ATOMIC;
         boolean excl = (o2 == '0');
         boolean pair = (o1 == '1');
         MemOp memop = if L == '1' then MemOp_LOAD else MemOp_STORE;
         integer elsize = 8 << UInt(size);
         integer regsize = if elsize == 64 then 64 else 32;
         integer datasize = if pair then elsize * 2 else elsize;


       Notes for all encodings

       For information about the CONSTRAINED UNPREDICTABLE behavior of this instruction, see Appendix J1
       Architectural Constraints on UNPREDICTABLE behaviors, and particularly LDXP on page J1-5407.


       Assembler symbols

       <Wt1>           Is the 32-bit name of the first general-purpose register to be transferred, encoded in the "Rt" field.

       <Wt2>           Is the 32-bit name of the second general-purpose register to be transferred, encoded in the "Rt2"
                       field.

       <Xt1>           Is the 64-bit name of the first general-purpose register to be transferred, encoded in the "Rt" field.

       <Xt2>           Is the 64-bit name of the second general-purpose register to be transferred, encoded in the "Rt2"
                       field.
<Xn|SP>       Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.


Operation

 bits(64) address;
 bits(datasize) data;
 constant integer dbytes = datasize DIV 8;
 boolean rt_unknown = FALSE;
 boolean rn_unknown = FALSE;

 if memop == MemOp_LOAD && pair && t == t2 then
     Constraint c = ConstrainUnpredictable();
    assert c IN {Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_UNKNOWN     rt_unknown = TRUE;     // result is UNKNOWN
         when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP         EndOfInstruction();

 if memop == MemOp_STORE && excl then
    if s == t || (pair && s == t2) then
         Constraint c = ConstrainUnpredictable();
         assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
        case c of
            when Constraint_UNKNOWN      rt_unknown = TRUE;      // store UNKNOWN value
            when Constraint_NONE         rt_unknown = FALSE;     // store original value
            when Constraint_UNDEF        UnallocatedEncoding();
            when Constraint_NOP          EndOfInstruction();
    if s == n && n != 31 then
         Constraint c = ConstrainUnpredictable();
         assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
        case c of
            when Constraint_UNKNOWN      rn_unknown = TRUE;      // address is UNKNOWN
            when Constraint_NONE         rn_unknown = FALSE;     // address is original base
            when Constraint_UNDEF        UnallocatedEncoding();
            when Constraint_NOP          EndOfInstruction();

 if n == 31 then
     CheckSPAlignment();
    address = SP[];
 elsif rn_unknown then
    address = bits(64) UNKNOWN;
 else
    address = X[n];

 case memop of
    when MemOp_STORE
         if rt_unknown then
            data = bits(datasize) UNKNOWN;
         elsif pair then
            assert excl;
            bits(datasize DIV 2) el1 = X[t];
            bits(datasize DIV 2) el2 = X[t2];
            data = if BigEndian() then el1 : el2 else el2 : el1;
         else
            data = X[t];

         if excl then
            // store {release} exclusive register|pair (atomic)
            bit status = '1';
            // Check whether the Exclusive Monitors are set to include the
            // physical memory locations corresponding to virtual address
            // range [address, address+dbytes-1].
            if AArch64.ExclusiveMonitorsPass(address, dbytes) then
                 // This atomic write will be rejected if it does not refer
                 // to the same physical locations after address translation.
                 Mem[address, dbytes, acctype] = data;
                 status = ExclusiveMonitorsStatus();
                       X[s] = ZeroExtend(status, 32);
                   else
                      // store release register (atomic)
                       Mem[address, dbytes, acctype] = data;

              when MemOp_LOAD
                   if excl then
                      // Tell the Exclusive Monitors to record a sequence of one or more atomic
                      // memory reads from virtual address range [address, address+dbytes-1].
                      // The Exclusive Monitor will only be set if all the reads are from the
                      // same dbytes-aligned physical address, to allow for the possibility of
                      // an atomicity break if the translation is changed between reads.
                       AArch64.SetExclusiveMonitors(address, dbytes);

                   if pair then
                      // load exclusive pair
                      assert excl;
                      if rt_unknown then
                           // ConstrainedUNPREDICTABLE case
                           X[t]  = bits(datasize) UNKNOWN;
                      elsif elsize == 32 then
                           // 32-bit load exclusive pair (atomic)
                           data = Mem[address, dbytes, acctype];
                           if BigEndian() then
                               X[t]  = data<datasize-1:elsize>;
                               X[t2] = data<elsize-1:0>;
                           else
                               X[t]  = data<elsize-1:0>;
                               X[t2] = data<datasize-1:elsize>;
                      else // elsize == 64
                           // 64-bit load exclusive pair (not atomic),
                           // but must be 128-bit aligned
                           if address != Align(address, dbytes) then
                              iswrite = FALSE;
                              secondstage = FALSE;
                              AArch64.Abort(address, AArch64.AlignmentFault(acctype, iswrite, secondstage));
                           X[t]  = Mem[address + 0, 8, acctype];
                           X[t2] = Mem[address + 8, 8, acctype];
                   else
                      // load {acquire} {exclusive} single register
                      data = Mem[address, dbytes, acctype];
                       X[t] = ZeroExtend(data, regsize);


platform: ARM
mnem: LDXR
description:
Load Exclusive Register loads a 32-bit word or a 64-bit doubleword from memory, and writes it to a register. The       (C6.6.110)
memory access is atomic. The PE marks the physical address being accessed as an exclusive access. This exclusive
access mark is checked by Store Exclusive instructions. See Synchronization and semaphores on page B2-103. For
information about memory accesses see Load/Store addressing modes on page C1-122.




  31 30 29 28 27 26 25 24 23 22 21 20            16 15 14            10 9             5 4             0
   1 x 0 0 1 0 0 0 0 1 0 (1) (1) (1) (1) (1) 0 (1) (1) (1) (1) (1)            Rn              Rt
   size                    o2 L o1        Rs        o0       Rt2


32-bit variant

Applies when size = 10.

LDXR <Wt>, [<Xn|SP>{,#0}]


64-bit variant

Applies when size = 11.

LDXR <Xt>, [<Xn|SP>{,#0}]


Decode for all variants of this encoding

 integer n = UInt(Rn);
 integer t = UInt(Rt);
 integer t2 = UInt(Rt2); // ignored by load/store single register
 integer s = UInt(Rs);    // ignored by all loads and store-release

 if o2:o1:o0 == '100' || o2:o1:o0 == '11x' then UnallocatedEncoding();
 if o1 == '1' && size<1> == '0' then UnallocatedEncoding();

 AccType acctype = if o0 == '1' then AccType_ORDERED else AccType_ATOMIC;
 boolean excl = (o2 == '0');
 boolean pair = (o1 == '1');
 MemOp memop = if L == '1' then MemOp_LOAD else MemOp_STORE;
 integer elsize = 8 << UInt(size);
 integer regsize = if elsize == 64 then 64 else 32;
 integer datasize = if pair then elsize * 2 else elsize;


Assembler symbols

<Wt>           Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

<Xt>           Is the 64-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

<Xn|SP>        Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.


Operation

 bits(64) address;
 bits(datasize) data;
 constant integer dbytes = datasize DIV 8;
 boolean rt_unknown = FALSE;
 boolean rn_unknown = FALSE;

 if memop == MemOp_LOAD && pair && t == t2 then
     Constraint c = ConstrainUnpredictable();
     assert c IN {Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
     case c of
                   when Constraint_UNKNOWN    rt_unknown = TRUE;      // result is UNKNOWN
                   when Constraint_UNDEF      UnallocatedEncoding();
                   when Constraint_NOP        EndOfInstruction();

         if memop == MemOp_STORE && excl then
              if s == t || (pair && s == t2) then
                   Constraint c = ConstrainUnpredictable();
                   assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
                   case c of
                      when Constraint_UNKNOWN    rt_unknown = TRUE;        // store UNKNOWN value
                      when Constraint_NONE       rt_unknown = FALSE;       // store original value
                      when Constraint_UNDEF      UnallocatedEncoding();
                      when Constraint_NOP        EndOfInstruction();
              if s == n && n != 31 then
                   Constraint c = ConstrainUnpredictable();
                   assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
                   case c of
                      when Constraint_UNKNOWN    rn_unknown = TRUE;        // address is UNKNOWN
                      when Constraint_NONE       rn_unknown = FALSE;       // address is original base
                      when Constraint_UNDEF      UnallocatedEncoding();
                      when Constraint_NOP        EndOfInstruction();

         if n == 31 then
              CheckSPAlignment();
              address = SP[];
         elsif rn_unknown then
              address = bits(64) UNKNOWN;
         else
              address = X[n];

         case memop of
              when MemOp_STORE
                   if rt_unknown then
                      data = bits(datasize) UNKNOWN;
                   elsif pair then
                      assert excl;
                      bits(datasize DIV 2) el1 = X[t];
                      bits(datasize DIV 2) el2 = X[t2];
                      data = if BigEndian() then el1 : el2 else el2 : el1;
                   else
                      data = X[t];

                   if excl then
                      // store {release} exclusive register|pair (atomic)
                      bit status = '1';
                      // Check whether the Exclusive Monitors are set to include the
                      // physical memory locations corresponding to virtual address
                      // range [address, address+dbytes-1].
                      if AArch64.ExclusiveMonitorsPass(address, dbytes) then
                           // This atomic write will be rejected if it does not refer
                           // to the same physical locations after address translation.
                           Mem[address, dbytes, acctype] = data;
                           status = ExclusiveMonitorsStatus();
                       X[s] = ZeroExtend(status, 32);
                   else
                      // store release register (atomic)
                       Mem[address, dbytes, acctype] = data;

              when MemOp_LOAD
                   if excl then
                      // Tell the Exclusive Monitors to record a sequence of one or more atomic
                      // memory reads from virtual address range [address, address+dbytes-1].
                      // The Exclusive Monitor will only be set if all the reads are from the
                      // same dbytes-aligned physical address, to allow for the possibility of
                      // an atomicity break if the translation is changed between reads.
                       AArch64.SetExclusiveMonitors(address, dbytes);

                   if pair then
      // load exclusive pair
      assert excl;
      if rt_unknown then
          // ConstrainedUNPREDICTABLE case
          X[t]   = bits(datasize) UNKNOWN;
      elsif elsize == 32 then
          // 32-bit load exclusive pair (atomic)
          data = Mem[address, dbytes, acctype];
          if BigEndian() then
               X[t]  = data<datasize-1:elsize>;
               X[t2] = data<elsize-1:0>;
          else
               X[t]  = data<elsize-1:0>;
               X[t2] = data<datasize-1:elsize>;
      else // elsize == 64
          // 64-bit load exclusive pair (not atomic),
          // but must be 128-bit aligned
          if address != Align(address, dbytes) then
              iswrite = FALSE;
              secondstage = FALSE;
              AArch64.Abort(address, AArch64.AlignmentFault(acctype, iswrite, secondstage));
          X[t]   = Mem[address + 0, 8, acctype];
          X[t2] = Mem[address + 8, 8, acctype];
   else
      // load {acquire} {exclusive} single register
      data = Mem[address, dbytes, acctype];
       X[t] = ZeroExtend(data, regsize);


platform: ARM
mnem: LDXRB
description:
      Load Exclusive Register Byte loads a byte from memory, zero-extends it and writes it to a register. The memory       (C6.6.111)
      access is atomic. The PE marks the physical address being accessed as an exclusive access. This exclusive access
      mark is checked by Store Exclusive instructions. See Synchronization and semaphores on page B2-103. For
      information about memory accesses see Load/Store addressing modes on page C1-122.




          31 30 29 28 27 26 25 24 23 22 21 20            16 15 14            10 9             5 4            0
          0 0 0 0 1 0 0 0 0 1 0 (1) (1) (1) (1) (1) 0 (1) (1) (1) (1) (1)             Rn              Rt
          size                     o2 L o1        Rs        o0       Rt2


      No offset variant

      LDXRB <Wt>, [<Xn|SP>{,#0}]


      Decode for this encoding

        integer n = UInt(Rn);
        integer t = UInt(Rt);
        integer t2 = UInt(Rt2); // ignored by load/store single register
        integer s = UInt(Rs);     // ignored by all loads and store-release

        if o2:o1:o0 == '100' || o2:o1:o0 == '11x' then UnallocatedEncoding();
        if o1 == '1' && size<1> == '0' then UnallocatedEncoding();

        AccType acctype = if o0 == '1' then AccType_ORDERED else AccType_ATOMIC;
        boolean excl = (o2 == '0');
        boolean pair = (o1 == '1');
        MemOp memop = if L == '1' then MemOp_LOAD else MemOp_STORE;
        integer elsize = 8 << UInt(size);
        integer regsize = if elsize == 64 then 64 else 32;
        integer datasize = if pair then elsize * 2 else elsize;


      Assembler symbols

      <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

      <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.


      Operation

        bits(64) address;
        bits(datasize) data;
        constant integer dbytes = datasize DIV 8;
        boolean rt_unknown = FALSE;
        boolean rn_unknown = FALSE;

        if memop == MemOp_LOAD && pair && t == t2 then
             Constraint c = ConstrainUnpredictable();
             assert c IN {Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
             case c of
                  when Constraint_UNKNOWN     rt_unknown = TRUE;      // result is UNKNOWN
                  when Constraint_UNDEF       UnallocatedEncoding();
                  when Constraint_NOP         EndOfInstruction();

        if memop == MemOp_STORE && excl then
             if s == t || (pair && s == t2) then
                  Constraint c = ConstrainUnpredictable();
                  assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
                  case c of
                     when Constraint_UNKNOWN      rt_unknown = TRUE;       // store UNKNOWN value
           when Constraint_NONE       rt_unknown = FALSE;       // store original value
           when Constraint_UNDEF      UnallocatedEncoding();
           when Constraint_NOP        EndOfInstruction();
   if s == n && n != 31 then
        Constraint c = ConstrainUnpredictable();
        assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
       case c of
           when Constraint_UNKNOWN    rn_unknown = TRUE;        // address is UNKNOWN
           when Constraint_NONE       rn_unknown = FALSE;       // address is original base
           when Constraint_UNDEF      UnallocatedEncoding();
           when Constraint_NOP        EndOfInstruction();

if n == 31 then
    CheckSPAlignment();
   address = SP[];
elsif rn_unknown then
   address = bits(64) UNKNOWN;
else
   address = X[n];

case memop of
   when MemOp_STORE
       if rt_unknown then
           data = bits(datasize) UNKNOWN;
       elsif pair then
           assert excl;
           bits(datasize DIV 2) el1 = X[t];
           bits(datasize DIV 2) el2 = X[t2];
           data = if BigEndian() then el1 : el2 else el2 : el1;
       else
           data = X[t];

       if excl then
           // store {release} exclusive register|pair (atomic)
           bit status = '1';
           // Check whether the Exclusive Monitors are set to include the
           // physical memory locations corresponding to virtual address
           // range [address, address+dbytes-1].
           if AArch64.ExclusiveMonitorsPass(address, dbytes) then
               // This atomic write will be rejected if it does not refer
               // to the same physical locations after address translation.
               Mem[address, dbytes, acctype] = data;
               status = ExclusiveMonitorsStatus();
           X[s] = ZeroExtend(status, 32);
       else
           // store release register (atomic)
           Mem[address, dbytes, acctype] = data;

   when MemOp_LOAD
       if excl then
           // Tell the Exclusive Monitors to record a sequence of one or more atomic
           // memory reads from virtual address range [address, address+dbytes-1].
           // The Exclusive Monitor will only be set if all the reads are from the
           // same dbytes-aligned physical address, to allow for the possibility of
           // an atomicity break if the translation is changed between reads.
           AArch64.SetExclusiveMonitors(address, dbytes);

       if pair then
           // load exclusive pair
           assert excl;
           if rt_unknown then
               // ConstrainedUNPREDICTABLE case
               X[t]   = bits(datasize) UNKNOWN;
           elsif elsize == 32 then
               // 32-bit load exclusive pair (atomic)
               data = Mem[address, dbytes, acctype];
               if BigEndian() then
                   X[t]   = data<datasize-1:elsize>;
                              X[t2] = data<elsize-1:0>;
                         else
                              X[t]  = data<elsize-1:0>;
                              X[t2] = data<datasize-1:elsize>;
                     else // elsize == 64
                         // 64-bit load exclusive pair (not atomic),
                         // but must be 128-bit aligned
                         if address != Align(address, dbytes) then
                             iswrite = FALSE;
                             secondstage = FALSE;
                             AArch64.Abort(address, AArch64.AlignmentFault(acctype, iswrite, secondstage));
                         X[t]   = Mem[address + 0, 8, acctype];
                         X[t2] = Mem[address + 8, 8, acctype];
                  else
                     // load {acquire} {exclusive} single register
                     data = Mem[address, dbytes, acctype];
                      X[t] = ZeroExtend(data, regsize);


platform: ARM
mnem: LDXRH
description:
Load Exclusive Register Halfword loads a halfword from memory, zero-extends it and writes it to a register. The       (C6.6.112)
memory access is atomic. The PE marks the physical address being accessed as an exclusive access. This exclusive
access mark is checked by Store Exclusive instructions. See Synchronization and semaphores on page B2-103. For
information about memory accesses see Load/Store addressing modes on page C1-122.




  31 30 29 28 27 26 25 24 23 22 21 20            16 15 14            10 9             5 4             0
   0 1 0 0 1 0 0 0 0 1 0 (1) (1) (1) (1) (1) 0 (1) (1) (1) (1) (1)            Rn              Rt
   size                    o2 L o1        Rs        o0       Rt2


No offset variant

LDXRH <Wt>, [<Xn|SP>{,#0}]


Decode for this encoding

 integer n = UInt(Rn);
 integer t = UInt(Rt);
 integer t2 = UInt(Rt2); // ignored by load/store single register
 integer s = UInt(Rs);    // ignored by all loads and store-release

 if o2:o1:o0 == '100' || o2:o1:o0 == '11x' then UnallocatedEncoding();
 if o1 == '1' && size<1> == '0' then UnallocatedEncoding();

 AccType acctype = if o0 == '1' then AccType_ORDERED else AccType_ATOMIC;
 boolean excl = (o2 == '0');
 boolean pair = (o1 == '1');
 MemOp memop = if L == '1' then MemOp_LOAD else MemOp_STORE;
 integer elsize = 8 << UInt(size);
 integer regsize = if elsize == 64 then 64 else 32;
 integer datasize = if pair then elsize * 2 else elsize;


Assembler symbols

<Wt>           Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

<Xn|SP>        Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.


Operation

 bits(64) address;
 bits(datasize) data;
 constant integer dbytes = datasize DIV 8;
 boolean rt_unknown = FALSE;
 boolean rn_unknown = FALSE;

 if memop == MemOp_LOAD && pair && t == t2 then
     Constraint c = ConstrainUnpredictable();
     assert c IN {Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
     case c of
         when Constraint_UNKNOWN      rt_unknown = TRUE;      // result is UNKNOWN
         when Constraint_UNDEF        UnallocatedEncoding();
         when Constraint_NOP          EndOfInstruction();

 if memop == MemOp_STORE && excl then
     if s == t || (pair && s == t2) then
         Constraint c = ConstrainUnpredictable();
         assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
         case c of
             when Constraint_UNKNOWN      rt_unknown = TRUE;       // store UNKNOWN value
                      when Constraint_NONE       rt_unknown = FALSE;       // store original value
                      when Constraint_UNDEF      UnallocatedEncoding();
                      when Constraint_NOP         EndOfInstruction();
              if s == n && n != 31 then
                   Constraint c = ConstrainUnpredictable();
                   assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
                   case c of
                      when Constraint_UNKNOWN    rn_unknown = TRUE;        // address is UNKNOWN
                      when Constraint_NONE       rn_unknown = FALSE;       // address is original base
                      when Constraint_UNDEF      UnallocatedEncoding();
                      when Constraint_NOP         EndOfInstruction();

         if n == 31 then
              CheckSPAlignment();
              address = SP[];
         elsif rn_unknown then
              address = bits(64) UNKNOWN;
         else
              address = X[n];

         case memop of
              when MemOp_STORE
                   if rt_unknown then
                      data = bits(datasize) UNKNOWN;
                   elsif pair then
                      assert excl;
                      bits(datasize DIV 2) el1 = X[t];
                      bits(datasize DIV 2) el2 = X[t2];
                      data = if BigEndian() then el1 : el2 else el2 : el1;
                   else
                      data = X[t];

                   if excl then
                      // store {release} exclusive register|pair (atomic)
                      bit status = '1';
                      // Check whether the Exclusive Monitors are set to include the
                      // physical memory locations corresponding to virtual address
                      // range [address, address+dbytes-1].
                      if AArch64.ExclusiveMonitorsPass(address, dbytes) then
                           // This atomic write will be rejected if it does not refer
                           // to the same physical locations after address translation.
                           Mem[address, dbytes, acctype] = data;
                           status = ExclusiveMonitorsStatus();
                       X[s] = ZeroExtend(status, 32);
                   else
                      // store release register (atomic)
                       Mem[address, dbytes, acctype] = data;

              when MemOp_LOAD
                   if excl then
                      // Tell the Exclusive Monitors to record a sequence of one or more atomic
                      // memory reads from virtual address range [address, address+dbytes-1].
                      // The Exclusive Monitor will only be set if all the reads are from the
                      // same dbytes-aligned physical address, to allow for the possibility of
                      // an atomicity break if the translation is changed between reads.
                       AArch64.SetExclusiveMonitors(address, dbytes);

                   if pair then
                      // load exclusive pair
                      assert excl;
                      if rt_unknown then
                           // ConstrainedUNPREDICTABLE case
                           X[t]  = bits(datasize) UNKNOWN;
                      elsif elsize == 32 then
                           // 32-bit load exclusive pair (atomic)
                           data = Mem[address, dbytes, acctype];
                           if BigEndian() then
                               X[t]  = data<datasize-1:elsize>;
               X[t2] = data<elsize-1:0>;
          else
               X[t]  = data<elsize-1:0>;
               X[t2] = data<datasize-1:elsize>;
      else // elsize == 64
          // 64-bit load exclusive pair (not atomic),
          // but must be 128-bit aligned
          if address != Align(address, dbytes) then
              iswrite = FALSE;
              secondstage = FALSE;
              AArch64.Abort(address, AArch64.AlignmentFault(acctype, iswrite, secondstage));
          X[t]   = Mem[address + 0, 8, acctype];
          X[t2] = Mem[address + 8, 8, acctype];
   else
      // load {acquire} {exclusive} single register
      data = Mem[address, dbytes, acctype];
       X[t] = ZeroExtend(data, regsize);


platform: ARM
mnem: LSL
description:
Logical shift left (register): Rd = LSL(Rn, Rm)       (C6.6.113)

This instruction is an alias of the LSLV instruction. This means that:

.       The encodings in this description are named to match the encodings of LSLV.

.       The description of LSLV gives the operational pseudocode for this instruction.




    31 30 29 28 27 26 25 24 23 22 21 20            16 15 14 13 12 11 10 9             5 4              0
    sf 0 0 1 1 0 1 0 1 1 0                  Rm          0 0 1 0 0 0             Rn              Rd
                                                                   op2


32-bit variant

Applies when sf = 0.

LSL <Wd>, <Wn>, <Wm>

is equivalent to

LSLV <Wd>, <Wn>, <Wm>

and is always the preferred disassembly.

64-bit variant

Applies when sf = 1.

LSL <Xd>, <Xn>, <Xm>

is equivalent to

LSLV <Xd>, <Xn>, <Xm>

and is always the preferred disassembly.


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Wm>            Is the 32-bit name of the second general-purpose source register holding a shift amount from 0 to
                31 in its bottom 5 bits, encoded in the "Rm" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Xm>            Is the 64-bit name of the second general-purpose source register holding a shift amount from 0 to
                63 in its bottom 6 bits, encoded in the "Rm" field.


Operation

The description of LSLV gives the operational pseudocode for this instruction.


platform: ARM
mnem: LSLV
description:
Logical shift left variable: Rd = LSL(Rn, Rm)       (C6.6.115)

This instruction is used by the alias LSL (register). The alias is always the preferred disassembly.




    31 30 29 28 27 26 25 24 23 22 21 20            16 15 14 13 12 11 10 9               5 4            0
    sf 0 0 1 1 0 1 0 1 1 0                  Rm         0 0 1 0 0 0              Rn              Rd
                                                                     op2


32-bit variant

Applies when sf = 0.

LSLV <Wd>, <Wn>, <Wm>


64-bit variant

Applies when sf = 1.

LSLV <Xd>, <Xn>, <Xm>


Decode for all variants of this encoding

  integer d = UInt(Rd);
  integer n = UInt(Rn);
  integer m = UInt(Rm);
  integer datasize = if sf == '1' then 64 else 32;
  ShiftType shift_type = DecodeShift(op2);


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Wm>            Is the 32-bit name of the second general-purpose source register holding a shift amount from 0 to
                31 in its bottom 5 bits, encoded in the "Rm" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Xm>            Is the 64-bit name of the second general-purpose source register holding a shift amount from 0 to
                63 in its bottom 6 bits, encoded in the "Rm" field.


Operation

  bits(datasize) result;
  bits(datasize) operand2 = X[m];

  result = ShiftReg(n, shift_type, UInt(operand2) MOD datasize);
  X[d] = result;


platform: ARM
mnem: LSR
description:
Logical shift right (register): Rd = LSR(Rn, Rm)       (C6.6.116)

This instruction is an alias of the LSRV instruction. This means that:

.      The encodings in this description are named to match the encodings of LSRV.

.      The description of LSRV gives the operational pseudocode for this instruction.




  31 30 29 28 27 26 25 24 23 22 21 20              16 15 14 13 12 11 10 9              5 4              0
   sf 0 0 1 1 0 1 0 1 1 0                   Rm         0 0 1 0 0 1              Rn              Rd
                                                                   op2


32-bit variant

Applies when sf = 0.

LSR <Wd>, <Wn>, <Wm>

is equivalent to

LSRV <Wd>, <Wn>, <Wm>

and is always the preferred disassembly.

64-bit variant

Applies when sf = 1.

LSR <Xd>, <Xn>, <Xm>

is equivalent to

LSRV <Xd>, <Xn>, <Xm>

and is always the preferred disassembly.


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Wm>            Is the 32-bit name of the second general-purpose source register holding a shift amount from 0 to
                31 in its bottom 5 bits, encoded in the "Rm" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Xm>            Is the 64-bit name of the second general-purpose source register holding a shift amount from 0 to
                63 in its bottom 6 bits, encoded in the "Rm" field.


Operation

The description of LSRV gives the operational pseudocode for this instruction.


platform: ARM
mnem: LSRV
description:
Logical shift right variable: Rd = LSR(Rn, Rm)       (C6.6.118)

This instruction is used by the alias LSR (register). The alias is always the preferred disassembly.




  31 30 29 28 27 26 25 24 23 22 21 20              16 15 14 13 12 11 10 9               5 4             0
  sf 0 0 1 1 0 1 0 1 1 0                    Rm         0 0 1 0 0 1              Rn              Rd
                                                                     op2


32-bit variant

Applies when sf = 0.

LSRV <Wd>, <Wn>, <Wm>


64-bit variant

Applies when sf = 1.

LSRV <Xd>, <Xn>, <Xm>


Decode for all variants of this encoding

 integer d = UInt(Rd);
 integer n = UInt(Rn);
 integer m = UInt(Rm);
 integer datasize = if sf == '1' then 64 else 32;
 ShiftType shift_type = DecodeShift(op2);


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Wm>            Is the 32-bit name of the second general-purpose source register holding a shift amount from 0 to
                31 in its bottom 5 bits, encoded in the "Rm" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Xm>            Is the 64-bit name of the second general-purpose source register holding a shift amount from 0 to
                63 in its bottom 6 bits, encoded in the "Rm" field.


Operation

 bits(datasize) result;
 bits(datasize) operand2 = X[m];

 result = ShiftReg(n, shift_type, UInt(operand2) MOD datasize);
 X[d] = result;


platform: ARM
mnem: MADD
description:
       Multiply-add: Rd = Ra + Rn * Rm       (C6.6.119)

       This instruction is used by the alias MUL. See the Alias conditions table for details of when each alias is preferred.




           31 30 29 28 27 26 25 24 23 22 21 20            16 15 14          10 9              5 4             0
           sf 0 0 1 1 0 1 1 0 0 0                  Rm         0       Ra               Rn             Rd
                                                              o0


       32-bit variant

       Applies when sf = 0.

       MADD <Wd>, <Wn>, <Wm>, <Wa>


       64-bit variant

       Applies when sf = 1.

       MADD <Xd>, <Xn>, <Xm>, <Xa>


       Decode for all variants of this encoding

         integer d = UInt(Rd);
         integer n = UInt(Rn);
         integer m = UInt(Rm);
         integer a = UInt(Ra);
         integer destsize = if sf == '1' then 64 else 32;
         integer datasize = destsize;
         boolean sub_op = (o0 == '1');


       Alias conditions


                            Alias                     is preferred when

                            MUL                       Ra == '11111'



       Assembler symbols

       <Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <Wn>            Is the 32-bit name of the first general-purpose source register holding the multiplicand, encoded in
                       the "Rn" field.

       <Wm>            Is the 32-bit name of the second general-purpose source register holding the multiplier, encoded in
                       the "Rm" field.

       <Wa>            Is the 32-bit name of the third general-purpose source register holding the addend, encoded in the
                       "Ra" field.

       <Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <Xn>            Is the 64-bit name of the first general-purpose source register holding the multiplicand, encoded in
                       the "Rn" field.

       <Xm>            Is the 64-bit name of the second general-purpose source register holding the multiplier, encoded in
                       the "Rm" field.
<Xa>          Is the 64-bit name of the third general-purpose source register holding the addend, encoded in the
              "Ra" field.


Operation

 bits(datasize) operand1 = X[n];
 bits(datasize) operand2 = X[m];
 bits(destsize) operand3 = X[a];

 integer result;

 if sub_op then
    result = UInt(operand3) - (UInt(operand1) * UInt(operand2));
 else
    result = UInt(operand3) + (UInt(operand1) * UInt(operand2));

 X[d] = result<destsize-1:0>;


platform: ARM
mnem: MNEG
description:
Multiply-negate: Rd = -(Rn * Rm)       (C6.6.120)

This instruction is an alias of the MSUB instruction. This means that:

.       The encodings in this description are named to match the encodings of MSUB.

.       The description of MSUB gives the operational pseudocode for this instruction.




    31 30 29 28 27 26 25 24 23 22 21 20            16 15 14          10 9             5 4              0
    sf 0 0 1 1 0 1 1 0 0 0                  Rm         1 1 1 1 1 1              Rn             Rd
                                                       o0      Ra


32-bit variant

Applies when sf = 0.

MNEG <Wd>, <Wn>, <Wm>

is equivalent to

MSUB <Wd>, <Wn>, <Wm>, WZR

and is always the preferred disassembly.

64-bit variant

Applies when sf = 1.

MNEG <Xd>, <Xn>, <Xm>

is equivalent to

MSUB <Xd>, <Xn>, <Xm>, XZR

and is always the preferred disassembly.


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the first general-purpose source register holding the multiplicand, encoded in
                the "Rn" field.

<Wm>            Is the 32-bit name of the second general-purpose source register holding the multiplier, encoded in
                the "Rm" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the first general-purpose source register holding the multiplicand, encoded in
                the "Rn" field.

<Xm>            Is the 64-bit name of the second general-purpose source register holding the multiplier, encoded in
                the "Rm" field.


Operation

The description of MSUB gives the operational pseudocode for this instruction.


platform: ARM
mnem: MOV
description:
Move between register and stack pointer: Rd = Rn       (C6.6.121)

This instruction is an alias of the ADD (immediate) instruction. This means that:

.      The encodings in this description are named to match the encodings of ADD (immediate).

.      The description of ADD (immediate) gives the operational pseudocode for this instruction.




  31 30 29 28 27 26 25 24 23 22 21                                   10 9              5 4              0
   sf 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0                                 Rn              Rd
     op S                     shift               imm12


32-bit variant

Applies when sf = 0.

MOV <Wd|WSP>, <Wn|WSP>

is equivalent to

ADD <Wd|WSP>, <Wn|WSP>, #0

and is the preferred disassembly when (Rd == '11111' || Rn == '11111').

64-bit variant

Applies when sf = 1.

MOV <Xd|SP>, <Xn|SP>

is equivalent to

ADD <Xd|SP>, <Xn|SP>, #0

and is the preferred disassembly when (Rd == '11111' || Rn == '11111').


Assembler symbols

<Wd|WSP>        Is the 32-bit name of the destination general-purpose register or stack pointer, encoded in the "Rd"
                field.

<Wn|WSP>        Is the 32-bit name of the source general-purpose register or stack pointer, encoded in the "Rn" field.

<Xd|SP>         Is the 64-bit name of the destination general-purpose register or stack pointer, encoded in the "Rd"
                field.

<Xn|SP>         Is the 64-bit name of the source general-purpose register or stack pointer, encoded in the "Rn" field.


Operation

The description of ADD (immediate) gives the operational pseudocode for this instruction.


platform: ARM
mnem: MOVK
description:
      Move 16-bit immediate into register, keeping other bits unchanged: Rd<shift+15:shift> = imm16       (C6.6.126)




          31 30 29 28 27 26 25 24 23 22 21 20                                               5 4               0
          sf 1 1 1 0 0 1 0 1           hw                        imm16                                Rd
              opc


      32-bit variant

      Applies when sf = 0.

      MOVK <Wd>, #<imm>{, LSL #<shift>}


      64-bit variant

      Applies when sf = 1.

      MOVK <Xd>, #<imm>{, LSL #<shift>}


      Decode for all variants of this encoding

        integer d = UInt(Rd);
        integer datasize = if sf == '1' then 64 else 32;
        bits(16) imm = imm16;
        integer pos;
        MoveWideOp opcode;

        case opc of
             when '00' opcode = MoveWideOp_N;
             when '10' opcode = MoveWideOp_Z;
             when '11' opcode = MoveWideOp_K;
             otherwise UnallocatedEncoding();

        if sf == '0' && hw<1> == '1' then UnallocatedEncoding();
        pos = UInt(hw:'0000');


      Assembler symbols

      <Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

      <Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

      <imm>           Is the 16-bit unsigned immediate, in the range 0 to 65535, encoded in the "imm16" field.

      <shift>         For the 32-bit variant: is the amount by which to shift the immediate left, either 0 (the default) or
                      16, encoded in the "hw" field as <shift>/16.

                      For the 64-bit variant: is the amount by which to shift the immediate left, either 0 (the default), 16,
                      32 or 48, encoded in the "hw" field as <shift>/16.


      Operation

        bits(datasize) result;

        if opcode == MoveWideOp_K then
             result = X[d];
        else
             result = Zeros();

        result<pos+15:pos> = imm;
if opcode == MoveWideOp_N then
   result = NOT(result);
X[d] = result;


platform: ARM
mnem: MOVN
description:
       Move inverse of shifted 16-bit immediate to register: Rd = NOT (LSL (imm16, shift))       (C6.6.127)

       This instruction is used by the alias MOV (inverted wide immediate). See the Alias conditions table for details of
       when each alias is preferred.




           31 30 29 28 27 26 25 24 23 22 21 20                                              5 4              0
           sf 0 0 1 0 0 1 0 1           hw                        imm16                               Rd
               opc


       32-bit variant

       Applies when sf = 0.

       MOVN <Wd>, #<imm>{, LSL #<shift>}


       64-bit variant

       Applies when sf = 1.

       MOVN <Xd>, #<imm>{, LSL #<shift>}


       Decode for all variants of this encoding

         integer d = UInt(Rd);
         integer datasize = if sf == '1' then 64 else 32;
         bits(16) imm = imm16;
         integer pos;
         MoveWideOp opcode;

         case opc of
              when '00' opcode = MoveWideOp_N;
              when '10' opcode = MoveWideOp_Z;
              when '11' opcode = MoveWideOp_K;
              otherwise UnallocatedEncoding();

         if sf == '0' && hw<1> == '1' then UnallocatedEncoding();
         pos = UInt(hw:'0000');


       Alias conditions


          Alias                  of variant         is preferred when

          MOV (inverted wide     64-bit             ! (IsZero(imm16) && hw != '00')
          immediate)

          MOV (inverted wide     32-bit             ! (IsZero(imm16) && hw != '00') && ! IsOnes(imm16)
          immediate)


       Assembler symbols

       <Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <imm>           Is the 16-bit unsigned immediate, in the range 0 to 65535, encoded in the "imm16" field.
<shift>       For the 32-bit variant: is the amount by which to shift the immediate left, either 0 (the default) or
              16, encoded in the "hw" field as <shift>/16.

              For the 64-bit variant: is the amount by which to shift the immediate left, either 0 (the default), 16,
              32 or 48, encoded in the "hw" field as <shift>/16.


Operation

 bits(datasize) result;

 if opcode == MoveWideOp_K then
    result = X[d];
 else
    result = Zeros();

 result<pos+15:pos> = imm;
 if opcode == MoveWideOp_N then
    result = NOT(result);
 X[d] = result;


platform: ARM
mnem: MOVZ
description:
       Move shifted 16-bit immediate to register: Rd = LSL (imm16, shift)       (C6.6.128)

       This instruction is used by the alias MOV (wide immediate). See the Alias conditions table for details of when each
       alias is preferred.




           31 30 29 28 27 26 25 24 23 22 21 20                                                5 4               0
           sf 1 0 1 0 0 1 0 1            hw                        imm16                                Rd
               opc


       32-bit variant

       Applies when sf = 0.

       MOVZ <Wd>, #<imm>{, LSL #<shift>}


       64-bit variant

       Applies when sf = 1.

       MOVZ <Xd>, #<imm>{, LSL #<shift>}


       Decode for all variants of this encoding

         integer d = UInt(Rd);
         integer datasize = if sf == '1' then 64 else 32;
         bits(16) imm = imm16;
         integer pos;
         MoveWideOp opcode;

         case opc of
              when '00' opcode = MoveWideOp_N;
              when '10' opcode = MoveWideOp_Z;
              when '11' opcode = MoveWideOp_K;
              otherwise UnallocatedEncoding();

         if sf == '0' && hw<1> == '1' then UnallocatedEncoding();
         pos = UInt(hw:'0000');


       Alias conditions


                             Alias                     is preferred when

                             MOV (wide                 ! (IsZero(imm16) && hw != '00')
                             immediate)


       Assembler symbols

       <Wd>             Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <Xd>             Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <imm>            Is the 16-bit unsigned immediate, in the range 0 to 65535, encoded in the "imm16" field.

       <shift>          For the 32-bit variant: is the amount by which to shift the immediate left, either 0 (the default) or
                        16, encoded in the "hw" field as <shift>/16.

                        For the 64-bit variant: is the amount by which to shift the immediate left, either 0 (the default), 16,
                        32 or 48, encoded in the "hw" field as <shift>/16.
Operation

 bits(datasize) result;

 if opcode == MoveWideOp_K then
    result = X[d];
 else
    result = Zeros();

 result<pos+15:pos> = imm;
 if opcode == MoveWideOp_N then
    result = NOT(result);
 X[d] = result;


platform: ARM
mnem: MRS
description:
Move from system register       (C6.6.129)




    31 30 29 28 27 26 25 24 23 22 21 20 19 18     16 15       12 11         8 7      5 4              0
    1 1 0 1 0 1 0 1 0 0 1 1 o0                op1        CRn         CRm          op2          Rt
                                   L


System variant

MRS <Xt>, <systemreg>


Decode for this encoding

  CheckSystemAccess('1':o0, op1, CRn, CRm, op2, Rt, L);

  integer t = UInt(Rt);

  integer sys_op0 = 2 + UInt(o0);
  integer sys_op1 = UInt(op1);
  integer sys_op2 = UInt(op2);
  integer sys_crn = UInt(CRn);
  integer sys_crm = UInt(CRm);
  boolean read = (L == '1');


Assembler symbols

<Xt>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rt" field.

<systemreg>     Is a system register name, encoded in the "o0:op1:CRn:CRm:op2".


Operation

  if read then
       X[t] = System_Get(sys_op0, sys_op1, sys_crn, sys_crm, sys_op2);
  else
       System_Put(sys_op0, sys_op1, sys_crn, sys_crm, sys_op2, X[t]);


platform: ARM
mnem: MSR
description:
Move immediate to process state field       (C6.6.130)




  31 30 29 28 27 26 25 24 23 22 21 20 19 18     16 15 14 13 12 11        8 7       5 4 3 2 1 0
  1 1 0 1 0 1 0 1 0 0 0 0 0                op1      0 1 0 0         CRm        op2    1 1 1 1 1




System variant

MSR <pstatefield>, #<imm>


Decode for this encoding

 CheckSystemAccess('00', op1, '0100', CRm, op2, '11111', '0');

 bits(4) operand = CRm;
 PSTATEField field;
 case op1:op2 of
     when '000 101' field = PSTATEField_SP;
     when '011 110' field = PSTATEField_DAIFSet;
     when '011 111' field = PSTATEField_DAIFClr;
     otherwise       UnallocatedEncoding();

 // Check that an AArch64 MSR/MRS access to the DAIF flags is permitted
 if op1 == '011' && PSTATE.EL == EL0 && SCTLR_EL1.UMA == '0' then
     AArch64.SystemRegisterTrap(EL1, '00', op2, op1, '0100', '11111', CRm, '0');


Assembler symbols

<pstatefield> Is a PSTATE field name, encoded in the "op1:op2" field. It can have the following values:

              SPSel       when op1 = 000, op2 = 101

              DAIFSet     when op1 = 011, op2 = 110

              DAIFClr     when op1 = 011, op2 = 111

              It is RESERVED when:

              .      op1 = 000, op2 = 0xx.

              .      op1 = 000, op2 = 100.

              .      op1 = 000, op2 = 11x.

              .      op1 = 001, op2 = xxx.

              .      op1 = 010, op2 = xxx.

              .      op1 = 011, op2 = 0xx.

              .      op1 = 011, op2 = 10x.

              .      op1 = 1xx, op2 = xxx.

<imm>         Is a 4-bit unsigned immediate, in the range 0 to 15, encoded in the "CRm" field.


Operation

 case field of
     when PSTATEField_SP
        PSTATE.SP = operand<0>;
     when PSTATEField_DAIFSet
        PSTATE.D = PSTATE.D OR operand<3>;
        PSTATE.A = PSTATE.A OR operand<2>;
                   PSTATE.I = PSTATE.I OR operand<1>;
                   PSTATE.F = PSTATE.F OR operand<0>;
              when PSTATEField_DAIFClr
                   PSTATE.D = PSTATE.D AND NOT(operand<3>);
                   PSTATE.A = PSTATE.A AND NOT(operand<2>);
                   PSTATE.I = PSTATE.I AND NOT(operand<1>);
                   PSTATE.F = PSTATE.F AND NOT(operand<0>);


platform: ARM
mnem: MSUB
description:
       Multiply-subtract: Rd = Ra - Rn * Rm       (C6.6.132)

       This instruction is used by the alias MNEG. See the Alias conditions table for details of when each alias is preferred.




           31 30 29 28 27 26 25 24 23 22 21 20            16 15 14          10 9              5 4             0
           sf 0 0 1 1 0 1 1 0 0 0                  Rm         1       Ra               Rn              Rd
                                                              o0


       32-bit variant

       Applies when sf = 0.

       MSUB <Wd>, <Wn>, <Wm>, <Wa>


       64-bit variant

       Applies when sf = 1.

       MSUB <Xd>, <Xn>, <Xm>, <Xa>


       Decode for all variants of this encoding

         integer d = UInt(Rd);
         integer n = UInt(Rn);
         integer m = UInt(Rm);
         integer a = UInt(Ra);
         integer destsize = if sf == '1' then 64 else 32;
         integer datasize = destsize;
         boolean sub_op = (o0 == '1');


       Alias conditions


                             Alias                    is preferred when

                             MNEG                     Ra == '11111'



       Assembler symbols

       <Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <Wn>            Is the 32-bit name of the first general-purpose source register holding the multiplicand, encoded in
                       the "Rn" field.

       <Wm>            Is the 32-bit name of the second general-purpose source register holding the multiplier, encoded in
                       the "Rm" field.

       <Wa>            Is the 32-bit name of the third general-purpose source register holding the minuend, encoded in the
                       "Ra" field.

       <Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <Xn>            Is the 64-bit name of the first general-purpose source register holding the multiplicand, encoded in
                       the "Rn" field.

       <Xm>            Is the 64-bit name of the second general-purpose source register holding the multiplier, encoded in
                       the "Rm" field.
<Xa>          Is the 64-bit name of the third general-purpose source register holding the minuend, encoded in the
              "Ra" field.


Operation

 bits(datasize) operand1 = X[n];
 bits(datasize) operand2 = X[m];
 bits(destsize) operand3 = X[a];

 integer result;

 if sub_op then
    result = UInt(operand3) - (UInt(operand1) * UInt(operand2));
 else
    result = UInt(operand3) + (UInt(operand1) * UInt(operand2));

 X[d] = result<destsize-1:0>;


platform: ARM
mnem: MUL
description:
Multiply: Rd = Rn * Rm       (C6.6.133)

This instruction is an alias of the MADD instruction. This means that:

.       The encodings in this description are named to match the encodings of MADD.

.       The description of MADD gives the operational pseudocode for this instruction.




    31 30 29 28 27 26 25 24 23 22 21 20            16 15 14          10 9             5 4              0
    sf 0 0 1 1 0 1 1 0 0 0                  Rm         0 1 1 1 1 1              Rn             Rd
                                                       o0      Ra


32-bit variant

Applies when sf = 0.

MUL <Wd>, <Wn>, <Wm>

is equivalent to

MADD <Wd>, <Wn>, <Wm>, WZR

and is always the preferred disassembly.

64-bit variant

Applies when sf = 1.

MUL <Xd>, <Xn>, <Xm>

is equivalent to

MADD <Xd>, <Xn>, <Xm>, XZR

and is always the preferred disassembly.


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the first general-purpose source register holding the multiplicand, encoded in
                the "Rn" field.

<Wm>            Is the 32-bit name of the second general-purpose source register holding the multiplier, encoded in
                the "Rm" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the first general-purpose source register holding the multiplicand, encoded in
                the "Rn" field.

<Xm>            Is the 64-bit name of the second general-purpose source register holding the multiplier, encoded in
                the "Rm" field.


Operation

The description of MADD gives the operational pseudocode for this instruction.


platform: ARM
mnem: MVN
description:
Bitwise NOT (shifted register): Rd = NOT shift(Rm, amount)       (C6.6.134)

This instruction is an alias of the ORN (shifted register) instruction. This means that:

.      The encodings in this description are named to match the encodings of ORN (shifted register).

.      The description of ORN (shifted register) gives the operational pseudocode for this instruction.




  31 30 29 28 27 26 25 24 23 22 21 20                16 15              10 9             5 4             0
   sf 0 1 0 1 0 1 0 shift 1                  Rm               imm6          1 1 1 1 1             Rd
      opc                           N                                             Rn


32-bit variant

Applies when sf = 0.

MVN <Wd>, <Wm>{, <shift> #<amount>}

is equivalent to

ORN <Wd>, WZR, <Wm>{, <shift> #<amount>}

and is always the preferred disassembly.

64-bit variant

Applies when sf = 1.

MVN <Xd>, <Xm>{, <shift> #<amount>}

is equivalent to

ORN <Xd>, XZR, <Xm>{, <shift> #<amount>}

and is always the preferred disassembly.


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wm>            Is the 32-bit name of the general-purpose source register, encoded in the "Rm" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xm>            Is the 64-bit name of the general-purpose source register, encoded in the "Rm" field.

<shift>         Is the optional shift to be applied to the final source, defaulting to LSL and encoded in the "shift"
                field. It can have the following values:

                LSL          when shift = 00

                LSR          when shift = 01

                ASR          when shift = 10

                ROR          when shift = 11

<amount>        For the 32-bit variant: is the shift amount, in the range 0 to 31, defaulting to 0 and encoded in the
                "imm6" field.

                For the 64-bit variant: is the shift amount, in the range 0 to 63, defaulting to 0 and encoded in the
                "imm6" field.
       Operation

       The description of ORN (shifted register) gives the operational pseudocode for this instruction.


platform: ARM
mnem: NEG
description:
Negate: Rd = 0 - shift(Rm, amount)       (C6.6.135)

This instruction is an alias of the SUB (shifted register) instruction. This means that:

.      The encodings in this description are named to match the encodings of SUB (shifted register).

.      The description of SUB (shifted register) gives the operational pseudocode for this instruction.




  31 30 29 28 27 26 25 24 23 22 21 20                16 15              10 9            5 4              0
   sf 1 0 0 1 0 1 1 shift 0                   Rm               imm6        1 1 1 1 1              Rd
     op S                                                                        Rn


32-bit variant

Applies when sf = 0.

NEG <Wd>, <Wm>{, <shift> #<amount>}

is equivalent to

SUB  <Wd>, WZR, <Wm> {, <shift> #<amount>}

and is always the preferred disassembly.

64-bit variant

Applies when sf = 1.

NEG <Xd>, <Xm>{, <shift> #<amount>}

is equivalent to

SUB  <Xd>, XZR, <Xm> {, <shift> #<amount>}

and is always the preferred disassembly.


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wm>            Is the 32-bit name of the general-purpose source register, encoded in the "Rm" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xm>            Is the 64-bit name of the general-purpose source register, encoded in the "Rm" field.

<shift>         Is the optional shift type to be applied to the second source operand, defaulting to LSL and encoded
                in the "shift" field. It can have the following values:

                LSL          when shift = 00

                LSR          when shift = 01

                ASR          when shift = 10

                It is RESERVED when shift = 11.

<amount>        For the 32-bit variant: is the shift amount, in the range 0 to 31, defaulting to 0 and encoded in the
                "imm6" field.

                For the 64-bit variant: is the shift amount, in the range 0 to 63, defaulting to 0 and encoded in the
                "imm6" field.
       Operation

       The description of SUB (shifted register) gives the operational pseudocode for this instruction.


platform: ARM
mnem: NEGS
description:
Negate, setting the condition flags: Rd = 0 - shift(Rm, amount)       (C6.6.136)

This instruction is an alias of the SUBS (shifted register) instruction. This means that:

.      The encodings in this description are named to match the encodings of SUBS (shifted register).

.      The description of SUBS (shifted register) gives the operational pseudocode for this instruction.




  31 30 29 28 27 26 25 24 23 22 21 20                16 15              10 9            5 4              0
   sf 1 1 0 1 0 1 1 shift 0                   Rm               imm6        1 1 1 1 1              Rd
     op S                                                                        Rn


32-bit variant

Applies when sf = 0.

NEGS <Wd>, <Wm>{, <shift> #<amount>}

is equivalent to

SUBS <Wd>, WZR, <Wm> {, <shift> #<amount>}

and is always the preferred disassembly.

64-bit variant

Applies when sf = 1.

NEGS <Xd>, <Xm>{, <shift> #<amount>}

is equivalent to

SUBS <Xd>, XZR, <Xm> {, <shift> #<amount>}

and is always the preferred disassembly.


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wm>            Is the 32-bit name of the general-purpose source register, encoded in the "Rm" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xm>            Is the 64-bit name of the general-purpose source register, encoded in the "Rm" field.

<shift>         Is the optional shift type to be applied to the second source operand, defaulting to LSL and encoded
                in the "shift" field. It can have the following values:

                LSL          when shift = 00

                LSR          when shift = 01

                ASR          when shift = 10

                It is RESERVED when shift = 11.

<amount>        For the 32-bit variant: is the shift amount, in the range 0 to 31, defaulting to 0 and encoded in the
                "imm6" field.

                For the 64-bit variant: is the shift amount, in the range 0 to 63, defaulting to 0 and encoded in the
                "imm6" field.
       Operation

       The description of SUBS (shifted register) gives the operational pseudocode for this instruction.


platform: ARM
mnem: NGC
description:
Negate with carry: Rd = 0 - Rm - 1 + C       (C6.6.137)

This instruction is an alias of the SBC instruction. This means that:

.      The encodings in this description are named to match the encodings of SBC.

.      The description of SBC gives the operational pseudocode for this instruction.




  31 30 29 28 27 26 25 24 23 22 21 20              16 15 14 13 12 11 10 9             5 4              0
   sf 1 0 1 1 0 1 0 0 0 0                   Rm         0 0 0 0 0 0 1 1 1 1 1                   Rd
     op S                                                                      Rn


32-bit variant

Applies when sf = 0.

NGC <Wd>, <Wm>

is equivalent to

SBC <Wd>, WZR, <Wm>

and is always the preferred disassembly.

64-bit variant

Applies when sf = 1.

NGC <Xd>, <Xm>

is equivalent to

SBC <Xd>, XZR, <Xm>

and is always the preferred disassembly.


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wm>            Is the 32-bit name of the general-purpose source register, encoded in the "Rm" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xm>            Is the 64-bit name of the general-purpose source register, encoded in the "Rm" field.


Operation

The description of SBC gives the operational pseudocode for this instruction.


platform: ARM
mnem: NGCS
description:
Negate with carry, setting the condition flags: Rd = 0 - Rm - 1 + C       (C6.6.138)

This instruction is an alias of the SBCS instruction. This means that:

.       The encodings in this description are named to match the encodings of SBCS.

.       The description of SBCS gives the operational pseudocode for this instruction.




    31 30 29 28 27 26 25 24 23 22 21 20            16 15 14 13 12 11 10 9            5 4              0
    sf 1 1 1 1 0 1 0 0 0 0                  Rm         0 0 0 0 0 0 1 1 1 1 1                   Rd
       op S                                                                    Rn


32-bit variant

Applies when sf = 0.

NGCS <Wd>, <Wm>

is equivalent to

SBCS <Wd>, WZR, <Wm>

and is always the preferred disassembly.

64-bit variant

Applies when sf = 1.

NGCS <Xd>, <Xm>

is equivalent to

SBCS <Xd>, XZR, <Xm>

and is always the preferred disassembly.


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wm>            Is the 32-bit name of the general-purpose source register, encoded in the "Rm" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xm>            Is the 64-bit name of the general-purpose source register, encoded in the "Rm" field.


Operation

The description of SBCS gives the operational pseudocode for this instruction.


platform: ARM
mnem: NOP
description:
No operation       (C6.6.139)

This instruction is an alias of the HINT instruction. This means that:

.      The encodings in this description are named to match the encodings of HINT.

.      The description of HINT gives the operational pseudocode for this instruction.




  31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11          8 7       5 4 3 2 1 0
   1 1 0 1 0 1 0 1 0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0 0 1 1 1 1 1
                                                                      CRm      op2


System variant

NOP

is equivalent to

HINT #0

and is always the preferred disassembly.


Operation

The description of HINT gives the operational pseudocode for this instruction.


platform: ARM
mnem: ORN
description:
       Bitwise inclusive OR NOT (shifted register): Rd = Rn OR NOT shift(Rm, amount)       (C6.6.140)

       This instruction is used by the alias MVN. See the Alias conditions table for details of when each alias is preferred.




           31 30 29 28 27 26 25 24 23 22 21 20            16 15             10 9              5 4             0
           sf 0 1 0 1 0 1 0 shift 1                Rm              imm6                Rn              Rd
               opc                         N


       32-bit variant

       Applies when sf = 0.

       ORN <Wd>, <Wn>, <Wm>{, <shift> #<amount>}


       64-bit variant

       Applies when sf = 1.

       ORN <Xd>, <Xn>, <Xm>{, <shift> #<amount>}


       Decode for all variants of this encoding

         integer d = UInt(Rd);
         integer n = UInt(Rn);
         integer m = UInt(Rm);
         integer datasize = if sf == '1' then 64 else 32;
         boolean setflags;
         LogicalOp op;
         case opc of
              when '00' op = LogicalOp_AND; setflags = FALSE;
              when '01' op = LogicalOp_ORR; setflags = FALSE;
              when '10' op = LogicalOp_EOR; setflags = FALSE;
              when '11' op = LogicalOp_AND; setflags = TRUE;

         if sf == '0' && imm6<5> == '1' then ReservedValue();

         ShiftType shift_type = DecodeShift(shift);
         integer shift_amount = UInt(imm6);
         boolean invert = (N == '1');


       Alias conditions


                            Alias                     is preferred when

                            MVN                       Rn == '11111'



       Assembler symbols

       <Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <Wn>            Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

       <Wm>            Is the 32-bit name of the second general-purpose source register, encoded in the "Rm" field.

       <Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <Xn>            Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.
<Xm>          Is the 64-bit name of the second general-purpose source register, encoded in the "Rm" field.

<shift>       Is the optional shift to be applied to the final source, defaulting to LSL and encoded in the "shift"
              field. It can have the following values:

              LSL          when shift = 00

              LSR          when shift = 01

              ASR          when shift = 10

              ROR          when shift = 11

<amount>      For the 32-bit variant: is the shift amount, in the range 0 to 31, defaulting to 0 and encoded in the
              "imm6" field.

              For the 64-bit variant: is the shift amount, in the range 0 to 63, defaulting to 0 and encoded in the
              "imm6" field.


Operation

 bits(datasize) operand1 = X[n];
 bits(datasize) operand2 = ShiftReg(m, shift_type, shift_amount);

 if invert then operand2 = NOT(operand2);

 case op of
    when LogicalOp_AND result = operand1 AND operand2;
    when LogicalOp_ORR result = operand1 OR        operand2;
    when LogicalOp_EOR result = operand1 EOR operand2;

 if setflags then
    PSTATE.<N,Z,C,V> = result<datasize-1>:IsZeroBit(result):'00';

 X[d] = result;


platform: ARM
mnem: ORR
description:
       Bitwise inclusive OR (immediate): Rd = Rn OR imm       (C6.6.141)

       This instruction is used by the alias MOV (bitmask immediate). See the Alias conditions table for details of when
       each alias is preferred.




           31 30 29 28 27 26 25 24 23 22 21               16 15             10 9             5 4             0
           sf 0 1 1 0 0 1 0 0 N                 immr               imms               Rn               Rd
               opc


       32-bit variant

       Applies when sf = 0 && N = 0.

       ORR <Wd|WSP>, <Wn>, #<imm>


       64-bit variant

       Applies when sf = 1.

       ORR <Xd|SP>, <Xn>, #<imm>


       Decode for all variants of this encoding

         integer d = UInt(Rd);
         integer n = UInt(Rn);
         integer datasize = if sf == '1' then 64 else 32;
         boolean setflags;
         LogicalOp op;
         case opc of
              when '00' op = LogicalOp_AND; setflags = FALSE;
              when '01' op = LogicalOp_ORR; setflags = FALSE;
              when '10' op = LogicalOp_EOR; setflags = FALSE;
              when '11' op = LogicalOp_AND; setflags = TRUE;

         bits(datasize) imm;
         if sf == '0' && N != '0' then ReservedValue();
         (imm, -) = DecodeBitMasks(N, imms, immr, TRUE);


       Alias conditions


                            Alias                    is preferred when

                            MOV (bitmask             Rn == '11111' && ! MoveWidePreferred(sf, N, imms, immr)
                            immediate)


       Assembler symbols

       <Wd|WSP>        Is the 32-bit name of the destination general-purpose register or stack pointer, encoded in the "Rd"
                       field.

       <Wn>            Is the 32-bit name of the general-purpose source register, encoded in the "Rn" field.

       <Xd|SP>         Is the 64-bit name of the destination general-purpose register or stack pointer, encoded in the "Rd"
                       field.

       <Xn>            Is the 64-bit name of the general-purpose source register, encoded in the "Rn" field.
<imm>         Is the bitmask immediate, encoded in "N:imms:immr".


Operation

 bits(datasize) result;
 bits(datasize) operand1 = X[n];
 bits(datasize) operand2 = imm;

 case op of
    when LogicalOp_AND result = operand1 AND operand2;
    when LogicalOp_ORR result = operand1 OR   operand2;
    when LogicalOp_EOR result = operand1 EOR operand2;

 if setflags then
    PSTATE.<N,Z,C,V> = result<datasize-1>:IsZeroBit(result):'00';

 if d == 31 && !setflags then
     SP[] = result;
 else
     X[d] = result;


platform: ARM
mnem: PRFM
description:
       Prefetch memory (immediate offset)       (C6.6.143)




           31 30 29 28 27 26 25 24 23 22 21                                   10 9             5 4             0
           1 1 1 1 1 0 0 1 1 0                          imm12                           Rn               Rt
           size                     opc


       Unsigned offset variant

       PRFM <prfop>, [<Xn|SP>{, #<pimm>}]


       Decode for this encoding

         boolean wback = FALSE;
         boolean postindex = FALSE;
         integer scale = UInt(size);
         bits(64) offset = LSL(ZeroExtend(imm12, 64), scale);


       Assembler symbols

       <prfop>         Is the prefetch operation, encoded in the "Rt" field. It can have the following values:

                       PLDL1KEEP   when Rt = 00000

                       PLDL1STRM   when Rt = 00001

                       PLDL2KEEP   when Rt = 00010

                       PLDL2STRM   when Rt = 00011

                       PLDL3KEEP   when Rt = 00100

                       PLDL3STRM   when Rt = 00101

                       #uimm5      when Rt = 0011x

                       PLIL1KEEP   when Rt = 01000

                       PLIL1STRM   when Rt = 01001

                       PLIL2KEEP   when Rt = 01010

                       PLIL2STRM   when Rt = 01011

                       PLIL3KEEP   when Rt = 01100

                       PLIL3STRM   when Rt = 01101

                       #uimm5      when Rt = 0111x

                       PSTL1KEEP   when Rt = 10000

                       PSTL1STRM   when Rt = 10001

                       PSTL2KEEP   when Rt = 10010

                       PSTL2STRM   when Rt = 10011

                       PSTL3KEEP   when Rt = 10100

                       PSTL3STRM   when Rt = 10101

                       #uimm5      when Rt = 1011x

                       #uimm5      when Rt = 11xxx

       <Xn|SP>         Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <pimm>          Is the optional positive immediate byte offset, a multiple of 8 in the range 0 to 32760, defaulting to
                       0 and encoded in the "imm12" field as <pimm>/8.
Shared decode for all encodings

 integer n = UInt(Rn);
 integer t = UInt(Rt);
 AccType acctype = AccType_NORMAL;
 MemOp memop;
 boolean signed;
 integer regsize;

 if opc<1> == '0' then
    // store or zero-extending load
    memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
    regsize = if size == '11' then 64 else 32;
    signed = FALSE;
 else
    if size == '11' then
         memop = MemOp_PREFETCH;
         if opc<0> == '1' then UnallocatedEncoding();
    else
         // sign-extending load
         memop = MemOp_LOAD;
         if size == '10' && opc<0> == '1' then UnallocatedEncoding();
         regsize = if opc<0> == '1' then 32 else 64;
         signed = TRUE;

 integer datasize = 8 << scale;


Operation

 bits(64) address;
 bits(datasize) data;
 boolean wb_unknown = FALSE;
 boolean rt_unknown = FALSE;

 if memop == MemOp_LOAD && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_WBSUPPRESS wback = FALSE;         // writeback is suppressed
         when Constraint_UNKNOWN    wb_unknown = TRUE;     // writeback is UNKNOWN
         when Constraint_UNDEF      UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if memop == MemOp_STORE && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_NONE       rt_unknown = FALSE;    // value stored is original value
         when Constraint_UNKNOWN    rt_unknown = TRUE;     // value stored is UNKNOWN
        when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
                   Mem[address, datasize DIV 8, acctype] = data;

              when MemOp_LOAD
                   data = Mem[address, datasize DIV 8, acctype];
                   if signed then
                       X[t] = SignExtend(data, regsize);
                   else
                       X[t] = ZeroExtend(data, regsize);

              when MemOp_PREFETCH
                   Prefetch(address, t<4:0>);

         if wback then
              if wb_unknown then
                   address = bits(64) UNKNOWN;
              elsif postindex then
                   address = address + offset;
              if n == 31 then
                   SP[] = address;
              else
                   X[n] = address;


platform: ARM
mnem: PRFUM
description:
       Prefetch memory (unscaled offset)       (C6.6.146)




           31 30 29 28 27 26 25 24 23 22 21 20                        12 11 10 9              5 4             0
           1 1 1 1 1 0 0 0 1 0 0                       imm9               0 0          Rn              Rt
           size                     opc


       Unscaled offset variant

       PRFUM <prfop>, [<Xn|SP>{, #<simm>}]


       Decode for this encoding

         boolean wback = FALSE;
         boolean postindex = FALSE;
         integer scale = UInt(size);
         bits(64) offset = SignExtend(imm9, 64);


       Assembler symbols

       <prfop>         Is the prefetch operation, encoded in the "Rt" field. It can have the following values:

                       PLDL1KEEP   when Rt = 00000

                       PLDL1STRM   when Rt = 00001

                       PLDL2KEEP   when Rt = 00010

                       PLDL2STRM   when Rt = 00011

                       PLDL3KEEP   when Rt = 00100

                       PLDL3STRM   when Rt = 00101

                       #uimm5      when Rt = 0011x

                       PLIL1KEEP   when Rt = 01000

                       PLIL1STRM   when Rt = 01001

                       PLIL2KEEP   when Rt = 01010

                       PLIL2STRM   when Rt = 01011

                       PLIL3KEEP   when Rt = 01100

                       PLIL3STRM   when Rt = 01101

                       #uimm5      when Rt = 0111x

                       PSTL1KEEP   when Rt = 10000

                       PSTL1STRM   when Rt = 10001

                       PSTL2KEEP   when Rt = 10010

                       PSTL2STRM   when Rt = 10011

                       PSTL3KEEP   when Rt = 10100

                       PSTL3STRM   when Rt = 10101

                       #uimm5      when Rt = 1011x

                       #uimm5      when Rt = 11xxx

       <Xn|SP>         Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.

       <simm>          Is the optional signed immediate byte offset, in the range -256 to 255, defaulting to 0 and encoded
                       in the "imm9" field.
Shared decode for all encodings

 integer n = UInt(Rn);
 integer t = UInt(Rt);
 AccType acctype = AccType_NORMAL;
 MemOp memop;
 boolean signed;
 integer regsize;

 if opc<1> == '0' then
    // store or zero-extending load
    memop = if opc<0> == '1' then MemOp_LOAD else MemOp_STORE;
    regsize = if size == '11' then 64 else 32;
    signed = FALSE;
 else
    if size == '11' then
         memop = MemOp_PREFETCH;
         if opc<0> == '1' then UnallocatedEncoding();
    else
         // sign-extending load
         memop = MemOp_LOAD;
         if size == '10' && opc<0> == '1' then UnallocatedEncoding();
         regsize = if opc<0> == '1' then 32 else 64;
         signed = TRUE;

 integer datasize = 8 << scale;


Operation

 bits(64) address;
 bits(datasize) data;
 boolean wb_unknown = FALSE;
 boolean rt_unknown = FALSE;

 if memop == MemOp_LOAD && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_WBSUPPRESS, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_WBSUPPRESS wback = FALSE;         // writeback is suppressed
         when Constraint_UNKNOWN    wb_unknown = TRUE;     // writeback is UNKNOWN
         when Constraint_UNDEF      UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if memop == MemOp_STORE && wback && n == t && n != 31 then
    c = ConstrainUnpredictable();
    assert c IN {Constraint_NONE, Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
    case c of
         when Constraint_NONE       rt_unknown = FALSE;    // value stored is original value
         when Constraint_UNKNOWN    rt_unknown = TRUE;     // value stored is UNKNOWN
        when Constraint_UNDEF       UnallocatedEncoding();
         when Constraint_NOP        EndOfInstruction();

 if n == 31 then
    if memop != MemOp_PREFETCH then CheckSPAlignment();
    address = SP[];
 else
    address = X[n];

 if ! postindex then
    address = address + offset;

 case memop of
    when MemOp_STORE
        if rt_unknown then
            data = bits(datasize) UNKNOWN;
        else
            data = X[t];
                   Mem[address, datasize DIV 8, acctype] = data;

              when MemOp_LOAD
                   data = Mem[address, datasize DIV 8, acctype];
                   if signed then
                       X[t] = SignExtend(data, regsize);
                   else
                       X[t] = ZeroExtend(data, regsize);

              when MemOp_PREFETCH
                   Prefetch(address, t<4:0>);

         if wback then
              if wb_unknown then
                   address = bits(64) UNKNOWN;
              elsif postindex then
                   address = address + offset;
              if n == 31 then
                   SP[] = address;
              else
                   X[n] = address;


platform: ARM
mnem: RBIT
description:
Reverse bit order       (C6.6.147)




  31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9                5 4              0
  sf 1 0 1 1 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0                                Rn              Rd
                                                                  opc


32-bit variant

Applies when sf = 0.

RBIT <Wd>, <Wn>


64-bit variant

Applies when sf = 1.

RBIT <Xd>, <Xn>


Decode for all variants of this encoding

 integer d = UInt(Rd);
 integer n = UInt(Rn);

 integer datasize = if sf == '1' then 64 else 32;

 RevOp op;
 case opc of
     when '00'
         op = RevOp_RBIT;
     when '01'
        op = RevOp_REV16;
     when '10'
        op = RevOp_REV32;
     when '11'
        if sf == '0' then UnallocatedEncoding();
        op = RevOp_REV64;


Assembler symbols

<Wd>           Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>           Is the 32-bit name of the general-purpose source register, encoded in the "Rn" field.

<Xd>           Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>           Is the 64-bit name of the general-purpose source register, encoded in the "Rn" field.


Operation

 bits(datasize) result;
 bits(6) V;
 integer vbit;

 case op of
     when RevOp_REV16 V = '001000';
     when RevOp_REV32 V = '011000';
     when RevOp_REV64 V = '111000';
     when RevOp_RBIT   V = if datasize == 64 then '111111' else '011111';
         result = X[n];
         for vbit = 0 to 5
              // Swap pairs of 2^vbit bits in result
              if V<vbit> == '1' then
                   bits(datasize) tmp = result;
                   integer vsize = 1 << vbit;
                   integer base = 0;
                   while base < datasize do
                      result<base+vsize-1:base> = tmp<base+(2*vsize)-1:base+vsize>;
                      result<base+(2*vsize)-1:base+vsize> = tmp<base+vsize-1:base>;
                      base = base + (2 * vsize);
         X[d] = result;


platform: ARM
mnem: RET
description:
Return from subroutine branches unconditionally to an address in a register, with a hint that this is a subroutine       (C6.6.148)
return.




  31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9                5 4 3 2 1 0
   1 1 0 1 0 1 1 0 0 1 0 1 1 1 1 1 0 0 0 0 0 0                               Rn          0 0 0 0 0
                              op


Integer variant

RET {<Xn>}


Decode for this encoding

 integer n = UInt(Rn);
 BranchType branch_type;

 case op of
     when '00' branch_type = BranchType_JMP;
     when '01' branch_type = BranchType_CALL;
     when '10' branch_type = BranchType_RET;
     otherwise UnallocatedEncoding();


Assembler symbols

<Xn>          Is the 64-bit name of the general-purpose register holding the address to be branched to, encoded in
              the "Rn" field. Defaults to X30 if absent.


Operation

 bits(64) target = X[n];

 if branch_type == BranchType_CALL then X[30] = PC[] + 4;
 BranchTo(target, branch_type);


platform: ARM
mnem: REV
description:
      Reverse bytes       (C6.6.149)




          31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9               5 4              0
          sf 1 0 1 1 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 1 x                                Rn              Rd
                                                                          opc


      32-bit variant

      Applies when sf = 0 && opc = 10.

      REV <Wd>, <Wn>


      64-bit variant

      Applies when sf = 1 && opc = 11.

      REV <Xd>, <Xn>


      Decode for all variants of this encoding

        integer d = UInt(Rd);
        integer n = UInt(Rn);

        integer datasize = if sf == '1' then 64 else 32;

        RevOp op;
        case opc of
             when '00'
                  op = RevOp_RBIT;
             when '01'
                  op = RevOp_REV16;
             when '10'
                  op = RevOp_REV32;
             when '11'
                  if sf == '0' then UnallocatedEncoding();
                  op = RevOp_REV64;


      Assembler symbols

      <Wd>             Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

      <Wn>             Is the 32-bit name of the general-purpose source register, encoded in the "Rn" field.

      <Xd>             Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

      <Xn>             Is the 64-bit name of the general-purpose source register, encoded in the "Rn" field.


      Operation

        bits(datasize) result;
        bits(6) V;
        integer vbit;

        case op of
             when RevOp_REV16 V = '001000';
             when RevOp_REV32 V = '011000';
             when RevOp_REV64 V = '111000';
             when RevOp_RBIT   V = if datasize == 64 then '111111' else '011111';
result = X[n];
for vbit = 0 to 5
    // Swap pairs of 2^vbit bits in result
    if V<vbit> == '1' then
       bits(datasize) tmp = result;
       integer vsize = 1 << vbit;
       integer base = 0;
       while base < datasize do
            result<base+vsize-1:base> = tmp<base+(2*vsize)-1:base+vsize>;
            result<base+(2*vsize)-1:base+vsize> = tmp<base+vsize-1:base>;
            base = base + (2 * vsize);
X[d] = result;


platform: ARM
mnem: REV16
description:
      Reverse bytes in 16-bit halfwords       (C6.6.150)




          31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9               5 4              0
          sf 1 0 1 1 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1                                Rn              Rd
                                                                          opc


      32-bit variant

      Applies when sf = 0.

      REV16 <Wd>, <Wn>


      64-bit variant

      Applies when sf = 1.

      REV16 <Xd>, <Xn>


      Decode for all variants of this encoding

        integer d = UInt(Rd);
        integer n = UInt(Rn);

        integer datasize = if sf == '1' then 64 else 32;

        RevOp op;
        case opc of
             when '00'
                  op = RevOp_RBIT;
             when '01'
                  op = RevOp_REV16;
             when '10'
                  op = RevOp_REV32;
             when '11'
                  if sf == '0' then UnallocatedEncoding();
                  op = RevOp_REV64;


      Assembler symbols

      <Wd>             Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

      <Wn>             Is the 32-bit name of the general-purpose source register, encoded in the "Rn" field.

      <Xd>             Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

      <Xn>             Is the 64-bit name of the general-purpose source register, encoded in the "Rn" field.


      Operation

        bits(datasize) result;
        bits(6) V;
        integer vbit;

        case op of
             when RevOp_REV16 V = '001000';
             when RevOp_REV32 V = '011000';
             when RevOp_REV64 V = '111000';
             when RevOp_RBIT   V = if datasize == 64 then '111111' else '011111';
result = X[n];
for vbit = 0 to 5
    // Swap pairs of 2^vbit bits in result
    if V<vbit> == '1' then
       bits(datasize) tmp = result;
       integer vsize = 1 << vbit;
       integer base = 0;
       while base < datasize do
            result<base+vsize-1:base> = tmp<base+(2*vsize)-1:base+vsize>;
            result<base+(2*vsize)-1:base+vsize> = tmp<base+vsize-1:base>;
            base = base + (2 * vsize);
X[d] = result;


platform: ARM
mnem: REV32
description:
Reverse bytes in 32-bit words       (C6.6.151)




    31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9               5 4              0
    1 1 0 1 1 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 1 0                                 Rn              Rd
    sf                                                              opc


64-bit variant

REV32 <Xd>, <Xn>


Decode for this encoding

  integer d = UInt(Rd);
  integer n = UInt(Rn);

  integer datasize = if sf == '1' then 64 else 32;

  RevOp op;
  case opc of
       when '00'
            op = RevOp_RBIT;
       when '01'
            op = RevOp_REV16;
       when '10'
            op = RevOp_REV32;
       when '11'
            if sf == '0' then UnallocatedEncoding();
            op = RevOp_REV64;


Assembler symbols

<Xd>             Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>             Is the 64-bit name of the general-purpose source register, encoded in the "Rn" field.


Operation

  bits(datasize) result;
  bits(6) V;
  integer vbit;

  case op of
       when RevOp_REV16 V = '001000';
       when RevOp_REV32 V = '011000';
       when RevOp_REV64 V = '111000';
       when RevOp_RBIT   V = if datasize == 64 then '111111' else '011111';

  result = X[n];
  for vbit = 0 to 5
       // Swap pairs of 2^vbit bits in result
       if V<vbit> == '1' then
            bits(datasize) tmp = result;
            integer vsize = 1 << vbit;
            integer base = 0;
            while base < datasize do
               result<base+vsize-1:base> = tmp<base+(2*vsize)-1:base+vsize>;
               result<base+(2*vsize)-1:base+vsize> = tmp<base+vsize-1:base>;
               base = base + (2 * vsize);
  X[d] = result;


platform: ARM
mnem: ROR
description:
Rotate right (immediate): Rd = ROR(Rs, shift)       (C6.6.152)

This instruction is an alias of the EXTR instruction. This means that:

.      The encodings in this description are named to match the encodings of EXTR.

.      The description of EXTR gives the operational pseudocode for this instruction.




  31 30 29 28 27 26 25 24 23 22 21 20              16 15              10 9              5 4              0
   sf 0 0 1 0 0 1 1 1 N 0                    Rm             imms                 Rn              Rd




32-bit variant

Applies when sf = 0 && N = 0 && imms = 0xxxxx.

ROR <Wd>, <Ws>, #<shift>

is equivalent to

EXTR <Wd>, <Ws>, <Ws>, #<shift>

and is the preferred disassembly when Rn == Rm.

64-bit variant

Applies when sf = 1 && N = 1.

ROR <Xd>, <Xs>, #<shift>

is equivalent to

EXTR <Xd>, <Xs>, <Xs>, #<shift>

and is the preferred disassembly when Rn == Rm.


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Ws>            Is the 32-bit name of the general-purpose source register, encoded in the "Rn" and "Rm" fields.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xs>            Is the 64-bit name of the general-purpose source register, encoded in the "Rn" and "Rm" fields.

<shift>         For the 32-bit variant: is the amount by which to rotate, in the range 0 to 31, encoded in the "imms"
                field.

                For the 64-bit variant: is the amount by which to rotate, in the range 0 to 63, encoded in the "imms"
                field.


Operation

The description of EXTR gives the operational pseudocode for this instruction.


platform: ARM
mnem: RORV
description:
Rotate right variable: Rd = ROR(Rn, Rm)       (C6.6.154)

This instruction is used by the alias ROR (register). The alias is always the preferred disassembly.




  31 30 29 28 27 26 25 24 23 22 21 20              16 15 14 13 12 11 10 9              5 4              0
  sf 0 0 1 1 0 1 0 1 1 0                    Rm         0 0 1 0 1 1              Rn              Rd
                                                                     op2


32-bit variant

Applies when sf = 0.

RORV <Wd>, <Wn>, <Wm>


64-bit variant

Applies when sf = 1.

RORV <Xd>, <Xn>, <Xm>


Decode for all variants of this encoding

 integer d = UInt(Rd);
 integer n = UInt(Rn);
 integer m = UInt(Rm);
 integer datasize = if sf == '1' then 64 else 32;
 ShiftType shift_type = DecodeShift(op2);


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Wm>            Is the 32-bit name of the second general-purpose source register holding a shift amount from 0 to
                31 in its bottom 5 bits, encoded in the "Rm" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

<Xm>            Is the 64-bit name of the second general-purpose source register holding a shift amount from 0 to
                63 in its bottom 6 bits, encoded in the "Rm" field.


Operation

 bits(datasize) result;
 bits(datasize) operand2 = X[m];

 result = ShiftReg(n, shift_type, UInt(operand2) MOD datasize);
 X[d] = result;


platform: ARM
mnem: SBC
description:
      Subtract with carry: Rd = Rn - Rm - 1 + C       (C6.6.155)

      This instruction is used by the alias NGC. See the Alias conditions table for details of when each alias is preferred.




          31 30 29 28 27 26 25 24 23 22 21 20            16 15 14 13 12 11 10 9              5 4             0
          sf 1 0 1 1 0 1 0 0 0 0                  Rm         0 0 0 0 0 0              Rn              Rd
             op S


      32-bit variant

      Applies when sf = 0.

      SBC <Wd>, <Wn>, <Wm>


      64-bit variant

      Applies when sf = 1.

      SBC <Xd>, <Xn>, <Xm>


      Decode for all variants of this encoding

        integer d = UInt(Rd);
        integer n = UInt(Rn);
        integer m = UInt(Rm);
        integer datasize = if sf == '1' then 64 else 32;
        boolean sub_op = (op == '1');
        boolean setflags = (S == '1');


      Alias conditions


                           Alias                     is preferred when

                           NGC                       Rn == '11111'



      Assembler symbols

      <Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

      <Wn>            Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

      <Wm>            Is the 32-bit name of the second general-purpose source register, encoded in the "Rm" field.

      <Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

      <Xn>            Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

      <Xm>            Is the 64-bit name of the second general-purpose source register, encoded in the "Rm" field.


      Operation

        bits(datasize) result;
        bits(datasize) operand1 = X[n];
        bits(datasize) operand2 = X[m];
        bits(4) nzcv;

        if sub_op then
   operand2 = NOT(operand2);

(result, nzcv) = AddWithCarry(operand1, operand2, PSTATE.C);

if setflags then
   PSTATE.<N,Z,C,V> = nzcv;

X[d] = result;


platform: ARM
mnem: SBCS
description:
      Subtract with carry, setting the condition flags: Rd = Rn - Rm - 1 + C       (C6.6.156)

      This instruction is used by the alias NGCS. See the Alias conditions table for details of when each alias is preferred.




          31 30 29 28 27 26 25 24 23 22 21 20            16 15 14 13 12 11 10 9               5 4            0
          sf 1 1 1 1 0 1 0 0 0 0                  Rm         0 0 0 0 0 0              Rn              Rd
             op S


      32-bit variant

      Applies when sf = 0.

      SBCS <Wd>, <Wn>, <Wm>


      64-bit variant

      Applies when sf = 1.

      SBCS <Xd>, <Xn>, <Xm>


      Decode for all variants of this encoding

        integer d = UInt(Rd);
        integer n = UInt(Rn);
        integer m = UInt(Rm);
        integer datasize = if sf == '1' then 64 else 32;
        boolean sub_op = (op == '1');
        boolean setflags = (S == '1');


      Alias conditions


                           Alias                     is preferred when

                           NGCS                      Rn == '11111'



      Assembler symbols

      <Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

      <Wn>            Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

      <Wm>            Is the 32-bit name of the second general-purpose source register, encoded in the "Rm" field.

      <Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

      <Xn>            Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

      <Xm>            Is the 64-bit name of the second general-purpose source register, encoded in the "Rm" field.


      Operation

        bits(datasize) result;
        bits(datasize) operand1 = X[n];
        bits(datasize) operand2 = X[m];
        bits(4) nzcv;

        if sub_op then
   operand2 = NOT(operand2);

(result, nzcv) = AddWithCarry(operand1, operand2, PSTATE.C);

if setflags then
   PSTATE.<N,Z,C,V> = nzcv;

X[d] = result;


platform: ARM
mnem: SBFIZ
description:
Signed bitfield insert in zero, with sign replication to left and zeros to right       (C6.6.157)

This instruction is an alias of the SBFM instruction. This means that:

.       The encodings in this description are named to match the encodings of SBFM.

.       The description of SBFM gives the operational pseudocode for this instruction.




    31 30 29 28 27 26 25 24 23 22 21                16 15                10 9            5 4               0
    sf 0 0 1 0 0 1 1 0 N                  immr                 imms               Rn               Rd
        opc


32-bit variant

Applies when sf = 0 && N = 0.

SBFIZ <Wd>, <Wn>, #<lsb>, #<width>

is equivalent to

SBFM <Wd>, <Wn>, #(-<lsb> MOD 32), #(<width>-1)

and is the preferred disassembly when UInt(imms) < UInt(immr).

64-bit variant

Applies when sf = 1 && N = 1.

SBFIZ <Xd>, <Xn>, #<lsb>, #<width>

is equivalent to

SBFM <Xd>, <Xn>, #(-<lsb> MOD 64), #(<width>-1)

and is the preferred disassembly when UInt(imms) < UInt(immr).


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the general-purpose source register, encoded in the "Rn" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the general-purpose source register, encoded in the "Rn" field.

<lsb>           For the 32-bit variant: is the bit number of the lsb of the destination bitfield, in the range 0 to 31.

                For the 64-bit variant: is the bit number of the lsb of the destination bitfield, in the range 0 to 63.

<width>         For the 32-bit variant: is the width of the bitfield, in the range 1 to 32-<lsb>.

                For the 64-bit variant: is the width of the bitfield, in the range 1 to 64-<lsb>.


Operation

The description of SBFM gives the operational pseudocode for this instruction.


platform: ARM
mnem: SBFM
description:
Signed bitfield move, with sign replication to left and zeros to right       (C6.6.158)

This instruction is used by the aliases ASR (immediate), SBFIZ, SBFX, SXTB, SXTH, and SXTW. See the Alias
conditions on page C6-678 table for details of when each alias is preferred.




  31 30 29 28 27 26 25 24 23 22 21                 16 15              10 9         5 4              0
  sf 0 0 1 0 0 1 1 0 N                   immr               imms             Rn            Rd
      opc


32-bit variant

Applies when sf = 0 && N = 0.

SBFM <Wd>, <Wn>, #<immr>, #<imms>


64-bit variant

Applies when sf = 1 && N = 1.

SBFM <Xd>, <Xn>, #<immr>, #<imms>


Decode for all variants of this encoding

 integer d = UInt(Rd);
 integer n = UInt(Rn);
 integer datasize = if sf == '1' then 64 else 32;

 boolean inzero;
 boolean extend;
 integer R;
 integer S;
 bits(datasize) wmask;
 bits(datasize) tmask;

 case opc of
     when '00' inzero = TRUE;      extend = TRUE;      // SBFM
     when '01' inzero = FALSE; extend = FALSE;         // BFM
     when '10' inzero = TRUE;      extend = FALSE;     // UBFM
     when '11' UnallocatedEncoding();

 if sf == '1' && N != '1' then ReservedValue();
 if sf == '0' && (N != '0' || immr<5> != '0' || imms<5> != '0') then ReservedValue();

 R = UInt(immr);
 S = UInt(imms);
 (wmask, tmask) = DecodeBitMasks(N, imms, immr, FALSE);
       Alias conditions


          Alias                  of variant            is preferred when

          ASR (immediate)        32-bit                imms == '011111'

          ASR (immediate)        64-bit                imms == '111111'

          SBFIZ                  -                     UInt(imms) < UInt(immr)

          SBFX                   -                     BFXPreferred(sf, opc<1>, imms, immr)

          SXTB                   -                     immr == '000000' && imms == '000111'

          SXTH                   -                     immr == '000000' && imms == '001111'

          SXTW                   -                     immr == '000000' && imms == '011111'



       Assembler symbols

       <Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <Wn>            Is the 32-bit name of the general-purpose source register, encoded in the "Rn" field.

       <Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

       <Xn>            Is the 64-bit name of the general-purpose source register, encoded in the "Rn" field.

       <immr>          For the 32-bit variant: is the right rotate amount, in the range 0 to 31, encoded in the "immr" field.

                       For the 64-bit variant: is the right rotate amount, in the range 0 to 63, encoded in the "immr" field.

       <imms>          For the 32-bit variant: is the leftmost bit number to be moved from the source, in the range 0 to 31,
                       encoded in the "imms" field.

                       For the 64-bit variant: is the leftmost bit number to be moved from the source, in the range 0 to 63,
                       encoded in the "imms" field.


       Operation

         bits(datasize) dst = if inzero then Zeros() else X[d];
         bits(datasize) src = X[n];

         // perform bitfield move on low bits
         bits(datasize) bot = (dst AND NOT(wmask)) OR (ROR(src, R) AND wmask);

         // determine extension bits (sign, zero or dest register)
         bits(datasize) top = if extend then Replicate(src<S>) else dst;

         // combine extension bits and result bits
         X[d] = (top AND NOT(tmask)) OR (bot AND tmask);


platform: ARM
mnem: SBFX
description:
Signed bitfield extract       (C6.6.159)

This instruction is an alias of the SBFM instruction. This means that:

.      The encodings in this description are named to match the encodings of SBFM.

.      The description of SBFM gives the operational pseudocode for this instruction.




  31 30 29 28 27 26 25 24 23 22 21                  16 15                10 9            5 4              0
   sf 0 0 1 0 0 1 1 0 N                   immr                imms                Rn              Rd
      opc


32-bit variant

Applies when sf = 0 && N = 0.

SBFX <Wd>, <Wn>, #<lsb>, #<width>

is equivalent to

SBFM <Wd>, <Wn>, #<lsb>, #(<lsb>+<width>-1)

and is the preferred disassembly when BFXPreferred(sf, opc<1>, imms, immr).

64-bit variant

Applies when sf = 1 && N = 1.

SBFX <Xd>, <Xn>, #<lsb>, #<width>

is equivalent to

SBFM <Xd>, <Xn>, #<lsb>, #(<lsb>+<width>-1)

and is the preferred disassembly when BFXPreferred(sf, opc<1>, imms, immr).


Assembler symbols

<Wd>            Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the general-purpose source register, encoded in the "Rn" field.

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the general-purpose source register, encoded in the "Rn" field.

<lsb>           For the 32-bit variant: is the bit number of the lsb of the source bitfield, in the range 0 to 31.

                For the 64-bit variant: is the bit number of the lsb of the source bitfield, in the range 0 to 63.

<width>         For the 32-bit variant: is the width of the bitfield, in the range 1 to 32-<lsb>.

                For the 64-bit variant: is the width of the bitfield, in the range 1 to 64-<lsb>.


Operation

The description of SBFM gives the operational pseudocode for this instruction.


platform: ARM
mnem: SDIV
description:
      Signed Divide divides a signed integer register value by a signed integer register value, and writes the result to the       (C6.6.160)
      destination register of the same size as source registers, 32-bit or 64-bit. The condition flags are not affected. That
      is, it performs a signed divide: Rd = Rn / Rm.




          31 30 29 28 27 26 25 24 23 22 21 20             16 15 14 13 12 11 10 9              5 4              0
          sf 0 0 1 1 0 1 0 1 1 0                   Rm         0 0 0 0 1 1              Rn              Rd
                                                                             o1


      32-bit variant

      Applies when sf = 0.

      SDIV <Wd>, <Wn>, <Wm>


      64-bit variant

      Applies when sf = 1.

      SDIV <Xd>, <Xn>, <Xm>


      Decode for all variants of this encoding

        integer d = UInt(Rd);
        integer n = UInt(Rn);
        integer m = UInt(Rm);
        integer datasize = if sf == '1' then 64 else 32;
        boolean unsigned = (o1 == '0');


      Assembler symbols

      <Wd>             Is the 32-bit name of the general-purpose destination register, encoded in the "Rd" field.

      <Wn>             Is the 32-bit name of the first general-purpose source register, encoded in the "Rn" field.

      <Wm>             Is the 32-bit name of the second general-purpose source register, encoded in the "Rm" field.

      <Xd>             Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

      <Xn>             Is the 64-bit name of the first general-purpose source register, encoded in the "Rn" field.

      <Xm>             Is the 64-bit name of the second general-purpose source register, encoded in the "Rm" field.


      Overflow

      When using the 32-bit form of the instruction, if the signed integer division 0x8000 0000 / 0xFFFF FFFF is performed,
      the pseudocode produces the intermediate integer result +231, that overflows the 32-bit signed integer range. No
      indication of this overflow case is produced, and the 32-bit result written to <Rd> must be the bottom 32 bits of the
      binary representation of +231. So the result of the division is 0x8000 0000.

      Similarly, when using the 64-bit form of the instruction, if the signed integer division 0x8000 0000 0000 0000 /
      0xFFFF FFFF FFFF FFFF is performed, the result of the division is 0x8000 0000 0000 0000.


      Operation

        bits(datasize) operand1 = X[n];
        bits(datasize) operand2 = X[m];
        integer result;
if IsZero(operand2) then
   result = 0;
else
   result = RoundTowardsZero (Int(operand1, unsigned) / Int(operand2, unsigned));

X[d] = result<datasize-1:0>;


platform: ARM
mnem: SEV
description:
Send event       (C6.6.161)

This instruction is an alias of the HINT instruction. This means that:

.       The encodings in this description are named to match the encodings of HINT.

.       The description of HINT gives the operational pseudocode for this instruction.




    31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11         8 7       5 4 3 2 1 0
    1 1 0 1 0 1 0 1 0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 1 0 0 1 1 1 1 1
                                                                      CRm       op2


System variant

SEV

is equivalent to

HINT #4

and is always the preferred disassembly.


Operation

The description of HINT gives the operational pseudocode for this instruction.


platform: ARM
mnem: SEVL
description:
Send event locally       (C6.6.162)

This instruction is an alias of the HINT instruction. This means that:

.      The encodings in this description are named to match the encodings of HINT.

.      The description of HINT gives the operational pseudocode for this instruction.




  31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11          8 7       5 4 3 2 1 0
   1 1 0 1 0 1 0 1 0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 1 0 1 1 1 1 1 1
                                                                      CRm      op2


System variant

SEVL

is equivalent to

HINT #5

and is always the preferred disassembly.


Operation

The description of HINT gives the operational pseudocode for this instruction.


platform: ARM
mnem: SMADDL
description:
      Signed multiply-add long: Xd = Xa + Wn * Wm       (C6.6.163)

      This instruction is used by the alias SMULL. See the Alias conditions table for details of when each alias is
      preferred.




          31 30 29 28 27 26 25 24 23 22 21 20            16 15 14          10 9             5 4              0
          1 0 0 1 1 0 1 1 0 0 1                   Rm         0       Ra               Rn             Rd
                                   U                         o0


      64-bit variant

      SMADDL <Xd>, <Wn>, <Wm>, <Xa>


      Decode for this encoding

        integer d = UInt(Rd);
        integer n = UInt(Rn);
        integer m = UInt(Rm);
        integer a = UInt(Ra);
        integer destsize = 64;
        integer datasize = 32;
        boolean sub_op = (o0 == '1');
        boolean unsigned = (U == '1');


      Alias conditions


                           Alias                     is preferred when

                           SMULL                     Ra == '11111'



      Assembler symbols

      <Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

      <Wn>            Is the 32-bit name of the first general-purpose source register holding the multiplicand, encoded in
                      the "Rn" field.

      <Wm>            Is the 32-bit name of the second general-purpose source register holding the multiplier, encoded in
                      the "Rm" field.

      <Xa>            Is the 64-bit name of the third general-purpose source register holding the addend, encoded in the
                      "Ra" field.


      Operation

        bits(datasize) operand1 = X[n];
        bits(datasize) operand2 = X[m];
        bits(destsize) operand3 = X[a];

        integer result;

        if sub_op then
             result = Int(operand3, unsigned) - (Int(operand1, unsigned) * Int(operand2, unsigned));
        else
   result = Int(operand3, unsigned) + (Int(operand1, unsigned) * Int(operand2, unsigned));

X[d] = result<63:0>;


platform: ARM
mnem: SMC
description:
Generate exception targeting exception level 3       (C6.6.164)




    31 30 29 28 27 26 25 24 23 22 21 20                                              5 4 3 2 1 0
    1 1 0 1 0 1 0 0 0 0 0                                 imm16                         0 0 0 1 1




System variant

SMC #<imm>


Decode for this encoding

  bits(16) imm = imm16;


Assembler symbols

<imm>           Is a 16-bit unsigned immediate, in the range 0 to 65535, encoded in the "imm16" field.


Operation

  if !HaveEL(EL3) || PSTATE.EL == EL0 then
       UnallocatedEncoding();

  AArch64.CheckForSMCTrap(imm);

  if SCR_EL3.SMD == '1' then
       // SMC disabled
       AArch64.UndefinedFault();
  else
       AArch64.CallSecureMonitor(imm);


platform: ARM
mnem: SMNEGL
description:
Signed multiply-negate long: Xd = -(Wn * Wm)       (C6.6.165)

This instruction is an alias of the SMSUBL instruction. This means that:

.      The encodings in this description are named to match the encodings of SMSUBL.

.      The description of SMSUBL gives the operational pseudocode for this instruction.




  31 30 29 28 27 26 25 24 23 22 21 20              16 15 14          10 9             5 4              0
   1 0 0 1 1 0 1 1 0 0 1                    Rm         1 1 1 1 1 1              Rn             Rd
                             U                         o0      Ra


64-bit variant

SMNEGL <Xd>, <Wn>, <Wm>

is equivalent to

SMSUBL <Xd>, <Wn>, <Wm>, XZR

and is always the preferred disassembly.


Assembler symbols

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the first general-purpose source register holding the multiplicand, encoded in
                the "Rn" field.

<Wm>            Is the 32-bit name of the second general-purpose source register holding the multiplier, encoded in
                the "Rm" field.


Operation

The description of SMSUBL gives the operational pseudocode for this instruction.


platform: ARM
mnem: SMSUBL
description:
      Signed multiply-subtract long: Xd = Xa - Wn * Wm       (C6.6.166)

      This instruction is used by the alias SMNEGL. See the Alias conditions table for details of when each alias is
      preferred.




          31 30 29 28 27 26 25 24 23 22 21 20            16 15 14          10 9             5 4              0
          1 0 0 1 1 0 1 1 0 0 1                   Rm         1       Ra               Rn             Rd
                                   U                         o0


      64-bit variant

      SMSUBL <Xd>, <Wn>, <Wm>, <Xa>


      Decode for this encoding

        integer d = UInt(Rd);
        integer n = UInt(Rn);
        integer m = UInt(Rm);
        integer a = UInt(Ra);
        integer destsize = 64;
        integer datasize = 32;
        boolean sub_op = (o0 == '1');
        boolean unsigned = (U == '1');


      Alias conditions


                           Alias                     is preferred when

                           SMNEGL                    Ra == '11111'



      Assembler symbols

      <Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

      <Wn>            Is the 32-bit name of the first general-purpose source register holding the multiplicand, encoded in
                      the "Rn" field.

      <Wm>            Is the 32-bit name of the second general-purpose source register holding the multiplier, encoded in
                      the "Rm" field.

      <Xa>            Is the 64-bit name of the third general-purpose source register holding the minuend, encoded in the
                      "Ra" field.


      Operation

        bits(datasize) operand1 = X[n];
        bits(datasize) operand2 = X[m];
        bits(destsize) operand3 = X[a];

        integer result;

        if sub_op then
             result = Int(operand3, unsigned) - (Int(operand1, unsigned) * Int(operand2, unsigned));
        else
   result = Int(operand3, unsigned) + (Int(operand1, unsigned) * Int(operand2, unsigned));

X[d] = result<63:0>;


platform: ARM
mnem: SMULH
description:
Signed multiply high: Xd = bits<127:64> of Xn * Xm       (C6.6.167)




    31 30 29 28 27 26 25 24 23 22 21 20            16 15 14              10 9         5 4              0
    1 0 0 1 1 0 1 1 0 1 0                   Rm         0 (1) (1) (1) (1) (1)    Rn             Rd
                             U                                  Ra


64-bit variant

SMULH <Xd>, <Xn>, <Xm>


Decode for this encoding

  integer d = UInt(Rd);
  integer n = UInt(Rn);
  integer m = UInt(Rm);
  integer a = UInt(Ra);             // ignored by UMULH/SMULH
  integer destsize = 64;
  integer datasize = destsize;
  boolean unsigned = (U == '1');


Assembler symbols

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Xn>            Is the 64-bit name of the first general-purpose source register holding the multiplicand, encoded in
                the "Rn" field.

<Xm>            Is the 64-bit name of the second general-purpose source register holding the multiplier, encoded in
                the "Rm" field.


Operation

  bits(datasize) operand1 = X[n];
  bits(datasize) operand2 = X[m];

  integer result;

  result = Int(operand1, unsigned) * Int(operand2, unsigned);

  X[d] = result<127:64>;


platform: ARM
mnem: SMULL
description:
Signed multiply long: Xd = Wn * Wm       (C6.6.168)

This instruction is an alias of the SMADDL instruction. This means that:

.      The encodings in this description are named to match the encodings of SMADDL.

.      The description of SMADDL gives the operational pseudocode for this instruction.




  31 30 29 28 27 26 25 24 23 22 21 20              16 15 14          10 9             5 4              0
   1 0 0 1 1 0 1 1 0 0 1                    Rm         0 1 1 1 1 1              Rn             Rd
                             U                         o0      Ra


64-bit variant

SMULL <Xd>, <Wn>, <Wm>

is equivalent to

SMADDL <Xd>, <Wn>, <Wm>, XZR

and is always the preferred disassembly.


Assembler symbols

<Xd>            Is the 64-bit name of the general-purpose destination register, encoded in the "Rd" field.

<Wn>            Is the 32-bit name of the first general-purpose source register holding the multiplicand, encoded in
                the "Rn" field.

<Wm>            Is the 32-bit name of the second general-purpose source register holding the multiplier, encoded in
                the "Rm" field.


Operation

The description of SMADDL gives the operational pseudocode for this instruction.


platform: ARM
mnem: STLR
description:
      Store-Release Register stores a 32-bit word or a 64-bit doubleword to a memory location, from a register. The       (C6.6.169)
      instruction also has memory ordering semantics as described in Load-Acquire, Store-Release on page B2-88. For
      information about memory accesses see Load/Store addressing modes on page C1-122.




          31 30 29 28 27 26 25 24 23 22 21 20            16 15 14            10 9             5 4            0
          1 x 0 0 1 0 0 0 1 0 0 (1) (1) (1) (1) (1) 1 (1) (1) (1) (1) (1)             Rn              Rt
          size                     o2 L o1        Rs        o0       Rt2


      32-bit variant

      Applies when size = 10.

      STLR <Wt>, [<Xn|SP>{,#0}]


      64-bit variant

      Applies when size = 11.

      STLR <Xt>, [<Xn|SP>{,#0}]


      Decode for all variants of this encoding

        integer n = UInt(Rn);
        integer t = UInt(Rt);
        integer t2 = UInt(Rt2); // ignored by load/store single register
        integer s = UInt(Rs);     // ignored by all loads and store-release

        if o2:o1:o0 == '100' || o2:o1:o0 == '11x' then UnallocatedEncoding();
        if o1 == '1' && size<1> == '0' then UnallocatedEncoding();

        AccType acctype = if o0 == '1' then AccType_ORDERED else AccType_ATOMIC;
        boolean excl = (o2 == '0');
        boolean pair = (o1 == '1');
        MemOp memop = if L == '1' then MemOp_LOAD else MemOp_STORE;
        integer elsize = 8 << UInt(size);
        integer regsize = if elsize == 64 then 64 else 32;
        integer datasize = if pair then elsize * 2 else elsize;


      Assembler symbols

      <Wt>             Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

      <Xt>             Is the 64-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

      <Xn|SP>          Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.


      Operation

        bits(64) address;
        bits(datasize) data;
        constant integer dbytes = datasize DIV 8;
        boolean rt_unknown = FALSE;
        boolean rn_unknown = FALSE;

        if memop == MemOp_LOAD && pair && t == t2 then
             Constraint c = ConstrainUnpredictable();
             assert c IN {Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
             case c of
                  when Constraint_UNKNOWN     rt_unknown = TRUE;      // result is UNKNOWN
        when Constraint_UNDEF      UnallocatedEncoding();
        when Constraint_NOP        EndOfInstruction();

if memop == MemOp_STORE && excl then
   if s == t || (pair && s == t2) then
        Constraint c = ConstrainUnpredictable();
        assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
       case c of
           when Constraint_UNKNOWN    rt_unknown = TRUE;        // store UNKNOWN value
           when Constraint_NONE       rt_unknown = FALSE;       // store original value
           when Constraint_UNDEF      UnallocatedEncoding();
           when Constraint_NOP        EndOfInstruction();
   if s == n && n != 31 then
        Constraint c = ConstrainUnpredictable();
        assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
       case c of
           when Constraint_UNKNOWN    rn_unknown = TRUE;        // address is UNKNOWN
           when Constraint_NONE       rn_unknown = FALSE;       // address is original base
           when Constraint_UNDEF      UnallocatedEncoding();
           when Constraint_NOP        EndOfInstruction();

if n == 31 then
    CheckSPAlignment();
   address = SP[];
elsif rn_unknown then
   address = bits(64) UNKNOWN;
else
   address = X[n];

case memop of
   when MemOp_STORE
       if rt_unknown then
           data = bits(datasize) UNKNOWN;
       elsif pair then
           assert excl;
           bits(datasize DIV 2) el1 = X[t];
           bits(datasize DIV 2) el2 = X[t2];
           data = if BigEndian() then el1 : el2 else el2 : el1;
       else
           data = X[t];

        if excl then
           // store {release} exclusive register|pair (atomic)
           bit status = '1';
           // Check whether the Exclusive Monitors are set to include the
           // physical memory locations corresponding to virtual address
           // range [address, address+dbytes-1].
           if AArch64.ExclusiveMonitorsPass(address, dbytes) then
                // This atomic write will be rejected if it does not refer
                // to the same physical locations after address translation.
                Mem[address, dbytes, acctype] = data;
                status = ExclusiveMonitorsStatus();
            X[s] = ZeroExtend(status, 32);
        else
           // store release register (atomic)
            Mem[address, dbytes, acctype] = data;

   when MemOp_LOAD
        if excl then
           // Tell the Exclusive Monitors to record a sequence of one or more atomic
           // memory reads from virtual address range [address, address+dbytes-1].
           // The Exclusive Monitor will only be set if all the reads are from the
           // same dbytes-aligned physical address, to allow for the possibility of
           // an atomicity break if the translation is changed between reads.
            AArch64.SetExclusiveMonitors(address, dbytes);

        if pair then
           // load exclusive pair
                     assert excl;
                     if rt_unknown then
                         // ConstrainedUNPREDICTABLE case
                         X[t]   = bits(datasize) UNKNOWN;
                     elsif elsize == 32 then
                         // 32-bit load exclusive pair (atomic)
                         data = Mem[address, dbytes, acctype];
                         if BigEndian() then
                              X[t]  = data<datasize-1:elsize>;
                              X[t2] = data<elsize-1:0>;
                         else
                              X[t]  = data<elsize-1:0>;
                              X[t2] = data<datasize-1:elsize>;
                     else // elsize == 64
                         // 64-bit load exclusive pair (not atomic),
                         // but must be 128-bit aligned
                         if address != Align(address, dbytes) then
                             iswrite = FALSE;
                             secondstage = FALSE;
                             AArch64.Abort(address, AArch64.AlignmentFault(acctype, iswrite, secondstage));
                         X[t]   = Mem[address + 0, 8, acctype];
                         X[t2] = Mem[address + 8, 8, acctype];
                  else
                     // load {acquire} {exclusive} single register
                     data = Mem[address, dbytes, acctype];
                      X[t] = ZeroExtend(data, regsize);


platform: ARM
mnem: STLRB
description:
Store-Release Register Byte stores a byte from a 32-bit register to a memory location. The instruction also has       (C6.6.170)
memory ordering semantics as described in Load-Acquire, Store-Release on page B2-88. For information about
memory accesses see Load/Store addressing modes on page C1-122.




  31 30 29 28 27 26 25 24 23 22 21 20            16 15 14             10 9           5 4             0
  0 0 0 0 1 0 0 0 1 0 0 (1) (1) (1) (1) (1) 1 (1) (1) (1) (1) (1)            Rn              Rt
  size                    o2 L o1          Rs       o0        Rt2


No offset variant

STLRB <Wt>, [<Xn|SP>{,#0}]


Decode for this encoding

 integer n = UInt(Rn);
 integer t = UInt(Rt);
 integer t2 = UInt(Rt2); // ignored by load/store single register
 integer s = UInt(Rs);   // ignored by all loads and store-release

 if o2:o1:o0 == '100' || o2:o1:o0 == '11x' then UnallocatedEncoding();
 if o1 == '1' && size<1> == '0' then UnallocatedEncoding();

 AccType acctype = if o0 == '1' then AccType_ORDERED else AccType_ATOMIC;
 boolean excl = (o2 == '0');
 boolean pair = (o1 == '1');
 MemOp memop = if L == '1' then MemOp_LOAD else MemOp_STORE;
 integer elsize = 8 << UInt(size);
 integer regsize = if elsize == 64 then 64 else 32;
 integer datasize = if pair then elsize * 2 else elsize;


Assembler symbols

<Wt>          Is the 32-bit name of the general-purpose register to be transferred, encoded in the "Rt" field.

<Xn|SP>       Is the 64-bit name of the general-purpose base register or stack pointer, encoded in the "Rn" field.


Operation

 bits(64) address;
 bits(datasize) data;
 constant integer dbytes = datasize DIV 8;
 boolean rt_unknown = FALSE;
 boolean rn_unknown = FALSE;

 if memop == MemOp_LOAD && pair && t == t2 then
     Constraint c = ConstrainUnpredictable();
     assert c IN {Constraint_UNKNOWN, Constraint_UNDEF, Constraint_NOP};
     case c of
         when Constraint_UNKNOWN      rt_unknown = TRUE;       // result is UNKNOWN
         when Constraint_UNDEF        UnallocatedEncoding();
         when Constraint_NOP          EndOfInstruction();

 if memop == MemOp_STORE && excl then
     if s == t || (pair && s == t2) then
         Constraint c = ConstrainUnpredictable();
         assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
         case c of
             when Constraint_UNKNOWN       rt_unknown = TRUE;       // store UNKNOWN value
             when Constraint_NONE          rt_unknown = FALSE;      // store original value
                      when Constraint_UNDEF      UnallocatedEncoding();
                      when Constraint_NOP         EndOfInstruction();
              if s == n && n != 31 then
                   Constraint c = ConstrainUnpredictable();
                   assert c IN {Constraint_UNKNOWN, Constraint_NONE, Constraint_UNDEF, Constraint_NOP};
                   case c of
                      when Constraint_UNKNOWN    rn_unknown = TRUE;        // address is UNKNOWN
                      when Constraint_NONE       rn_unknown = FALSE;       // address is original base
                      when Constraint_UNDEF      UnallocatedEncoding();
                      when Constraint_NOP         EndOfInstruction();

         if n == 31 then
              CheckSPAlignment();
              address = SP[];
         elsif rn_unknown then
              address = bits(64) UNKNOWN;
         else
              address = X[n];

         case memop of
              when MemOp_STORE
                   if rt_unknown then
                      data = bits(datasize) UNKNOWN;
                   elsif pair then
                      assert excl;
                      bits(datasize DIV 2) el1 = X[t];
                      bits(datasize DIV 2) el2 = X[t2];
                      data = if BigEndian() then el1 : el2 else el2 : el1;
                   else
                      data = X[t];

                   if excl then
                      // store {release} exclusive register|pair (atomic)
                      bit status = '1';
                      // Check whether the Exclusive Monitors are set to include the
                      // physical memory locations corresponding to virtual address
                      // range [address, address+dbytes-1].
                      if AArch64.ExclusiveMonitorsPass(address, dbytes) then
                           // This atomic write will be rejected if it does not refer
                           // to the same physical locations after address translation.
                           Mem[address, dbytes, acctype] = data;
                           status = ExclusiveMonitorsStatus();
                       X[s] = ZeroExtend(status, 32);
                   else
                      // store release register (atomic)
                       Mem[address, dbytes, acctype] = data;

              when MemOp_LOAD
                   if excl then
                      // Tell the Exclusive Monitors to record a sequence of one or more atomic
                      // memory reads from virtual address range [address, address+dbytes-1].
                      // The Exclusive Monitor will only be set if all the reads are from the
                      // same dbytes-aligned physical address, to allow for the possibility of
                      // an atomicity break if the translation is changed between reads.
                       AArch64.SetExclusiveMonitors(address, dbytes);

                   if pair then
                      // load exclusive pair
                      assert excl;
                      if rt_unknown then
                           // ConstrainedUNPREDICTABLE case
                           X[t]  = bits(datasize) UNKNOWN;
                      elsif elsize == 32 then
                           // 32-bit load exclusive pair (atomic)
                           data = Mem[address, dbytes, acctype];
                           if BigEndian() then
                               X[t]  = data<datasize-1:elsize>;
                               X[t2] = data<elsize-1:0>;
          else
               X[t]  = data<elsize-1:0>;
               X[t2] = data<datasize-1:elsize>;
      else // elsize == 64
          // 64-bit load exclusive pair (not atomic),
          // but must be 128-bit aligned
          if address != Align(address, dbytes) then
              iswrite = FALSE;
              secondstage = FALSE;
              AArch64.Abort(address, AArch64.AlignmentFault(acctype, iswrite, secondstage));
          X[t]   = Mem[address + 0, 8, acctype];
          X[t2] = Mem[address + 8, 8, acctype];
   else
      // load {acquire} {exclusive} single register
      data = Mem[address, dbytes, acctype];
       X[t] = ZeroExtend(data, regsize);


