<?xml version="1.0" ?><?xml-stylesheet type="text/xsl" encoding="UTF-8" href="iform.xsl" version="1.0"?><!DOCTYPE instructionsection  PUBLIC '-//ARM//DTD instructionsection //EN'  'iform-p.dtd'><!-- Copyright (c) 2010-2026 Arm Limited or its affiliates. All rights reserved. --><!-- This document is Non-Confidential. This document may only be used and distributed in accordance with the terms of the agreement entered into by Arm and the party that Arm delivered this document to. --><instructionsection id="CPYPTRN" title="CPYPTRN, CPYMTRN, CPYETRN -- A64" type="instruction">
  <docvars>
    <docvar key="instr-class" value="general"/>
    <docvar key="isa" value="A64"/>
  </docvars>
  <heading>CPYPTRN, CPYMTRN, CPYETRN</heading>
  <desc>
    <brief>
      <para>Memory copy, reads and writes unprivileged, reads non-temporal</para>
    </brief>
    <authored>
      <para>These instructions copy a requested number of bytes in memory from a source address to a
destination address. The prologue, main, and epilogue instructions are expected to be run
in succession and to appear consecutively in memory: CPYPTRN, then CPYMTRN,
and then CPYETRN.</para>
      <para>CPYPTRN performs some preconditioning of the arguments suitable for using the
CPYMTRN instruction, and copies an <arm-defined-word>IMPLEMENTATION DEFINED</arm-defined-word> portion of the requested
number of bytes. CPYMTRN copies a further <arm-defined-word>IMPLEMENTATION DEFINED</arm-defined-word> portion of the
remaining bytes. CPYETRN copies any final remaining bytes.</para>
      <note>
        <para>The ability to copy an <arm-defined-word>IMPLEMENTATION DEFINED</arm-defined-word> number of bytes allows an implementation
to optimize how the bytes being copied are divided between the different instructions.</para>
      </note>
      <para>For more information on exceptions specific to memory copy instructions,
see <xref linkend="ARMARM_MDSec.memcpy_and_memset_exceptions">Memory Copy and Memory Set exceptions</xref>.</para>
      <para>The architecture supports two algorithms for the memory copy: option A and option B.
Which algorithm is used is <arm-defined-word>IMPLEMENTATION DEFINED</arm-defined-word>.</para>
      <note>
        <para>Portable software should not assume that the choice of algorithm is constant.</para>
      </note>
      <para>For CPYPTRN:</para>
      <list type="unordered">
        <listitem>
          <content>
            <para>If Xn[63:55] != '000000000', the copy size Xn is saturated to <hexnumber>0x007FFFFFFFFFFFFF</hexnumber>.</para>
          </content>
        </listitem>
        <listitem>
          <content>
            <para>After saturation is performed, the direction of the memory copy is based on
the following:</para>
            <para>If (Xs[55:0] &gt; Xd[55:0]) and (Xd[55:0] + saturated copy size) &gt; Xs[55:0], then the direction is forward.</para>
            <para>If (Xs[55:0] &lt; Xd[55:0]) and (Xs[55:0] + saturated copy size) &gt; Xd[55:0], then the direction is backward.</para>
            <para>Otherwise, the direction is an <arm-defined-word>IMPLEMENTATION DEFINED</arm-defined-word> choice between forward and backward.</para>
          </content>
        </listitem>
      </list>
      <para>On completion of CPYPTRN, option A:</para>
      <list type="unordered">
        <listitem>
          <content>PSTATE.{N,Z,C,V} are set to {0,0,0,0}.</content>
        </listitem>
        <listitem>
          <content>If the copy is in the forward direction, then:<list type="unordered">
              <listitem>
                <content>Xn holds -1 times the number of bytes in the saturated copy size remaining to be copied.</content>
              </listitem>
              <listitem>
                <content>Xs holds the original Xs + saturated copy size.</content>
              </listitem>
              <listitem>
                <content>Xd holds the original Xd + saturated copy size.</content>
              </listitem>
            </list>
          </content>
        </listitem>
        <listitem>
          <content>If the copy is in the backward direction, then:<list type="unordered">
              <listitem>
                <content>Xn holds the number of bytes in the saturated copy size remaining to be copied.</content>
              </listitem>
              <listitem>
                <content>Xs and Xd are unchanged.</content>
              </listitem>
            </list>
          </content>
        </listitem>
      </list>
      <para>On completion of CPYPTRN, option B:</para>
      <list type="unordered">
        <listitem>
          <content>If the copy is in the forward direction, then:<list type="unordered">
              <listitem>
                <content>Xn holds the number of bytes in the saturated copy size remaining to be copied.</content>
              </listitem>
              <listitem>
                <content>Xs holds the lowest address that has not been copied from.</content>
              </listitem>
              <listitem>
                <content>Xd holds the lowest address that has not been copied to.</content>
              </listitem>
              <listitem>
                <content>PSTATE.{N,Z,C,V} are set to {0,0,1,0}.</content>
              </listitem>
            </list>
          </content>
        </listitem>
        <listitem>
          <content>If the copy is in the backward direction, then:<list type="unordered">
              <listitem>
                <content>Xn holds the number of bytes in the saturated copy size remaining to be copied.</content>
              </listitem>
              <listitem>
                <content>Xs holds the highest address that has not been copied from + 1.</content>
              </listitem>
              <listitem>
                <content>Xd holds the highest address that has not been copied to + 1.</content>
              </listitem>
              <listitem>
                <content>PSTATE.{N,Z,C,V} are set to {1,0,1,0}.</content>
              </listitem>
            </list>
          </content>
        </listitem>
      </list>
      <para>For CPYMTRN, option A, when PSTATE.C = 0:</para>
      <list type="unordered">
        <listitem>
          <content>Xn holds a signed 64-bit integer.</content>
        </listitem>
        <listitem>
          <content>If the copy is in the forward direction (Xn holds a negative number), then:<list type="unordered">
              <listitem>
                <content>Xn holds -1 times the number of bytes remaining to be copied.</content>
              </listitem>
              <listitem>
                <content>Xs holds the lowest address to be copied from - Xn.</content>
              </listitem>
              <listitem>
                <content>Xd holds the lowest address to be copied to - Xn.</content>
              </listitem>
              <listitem>
                <content>On completion of the instruction, Xn holds -1 times the number of bytes
remaining to be copied.</content>
              </listitem>
            </list>
          </content>
        </listitem>
        <listitem>
          <content>If the copy is in the backward direction (Xn holds a positive number), then:<list type="unordered">
              <listitem>
                <content>Xn holds the number of bytes remaining to be copied.</content>
              </listitem>
              <listitem>
                <content>Xs holds the highest address to be copied from + 1 - Xn.</content>
              </listitem>
              <listitem>
                <content>Xd holds the highest address to be copied to + 1 - Xn.</content>
              </listitem>
              <listitem>
                <content>On completion of the instruction, Xn holds the number of bytes
remaining to be copied.</content>
              </listitem>
            </list>
          </content>
        </listitem>
      </list>
      <para>For CPYMTRN, option B, when PSTATE.C = 1:</para>
      <list type="unordered">
        <listitem>
          <content>Xn holds the number of bytes remaining to be copied.</content>
        </listitem>
        <listitem>
          <content>If the copy is in the forward direction (PSTATE.N == 0), then:<list type="unordered">
              <listitem>
                <content>Xs holds the lowest address to be copied from.</content>
              </listitem>
              <listitem>
                <content>Xd holds the lowest address to be copied to.</content>
              </listitem>
              <listitem>
                <content>On completion of the instruction:<list type="unordered">
                    <listitem>
                      <content>Xn holds the number of bytes remaining to be copied.</content>
                    </listitem>
                    <listitem>
                      <content>Xs holds the lowest address that has not been copied from.</content>
                    </listitem>
                    <listitem>
                      <content>Xd holds the lowest address that has not been copied to.</content>
                    </listitem>
                  </list>
                </content>
              </listitem>
            </list>
          </content>
        </listitem>
        <listitem>
          <content>If the copy is in the backward direction (PSTATE.N == 1), then:<list type="unordered">
              <listitem>
                <content>Xs holds the highest address to be copied from + 1.</content>
              </listitem>
              <listitem>
                <content>Xd holds the highest address to be copied to + 1.</content>
              </listitem>
              <listitem>
                <content>On completion of the instruction:<list type="unordered">
                    <listitem>
                      <content>Xn holds the number of bytes remaining to be copied.</content>
                    </listitem>
                    <listitem>
                      <content>Xs holds the highest address that has not been copied from + 1.</content>
                    </listitem>
                    <listitem>
                      <content>Xd holds the highest address that has not been copied to + 1.</content>
                    </listitem>
                  </list>
                </content>
              </listitem>
            </list>
          </content>
        </listitem>
      </list>
      <para>For CPYETRN, option A, when PSTATE.C = 0:</para>
      <list type="unordered">
        <listitem>
          <content>Xn holds a signed 64-bit integer.</content>
        </listitem>
        <listitem>
          <content>If the copy is in the forward direction (Xn holds a negative number), then:<list type="unordered">
              <listitem>
                <content>Xn holds -1 times the number of bytes remaining to be copied.</content>
              </listitem>
              <listitem>
                <content>Xs holds the lowest address to be copied from - Xn.</content>
              </listitem>
              <listitem>
                <content>Xd holds the lowest address to be copied to - Xn.</content>
              </listitem>
            </list>
          </content>
        </listitem>
        <listitem>
          <content>
            <para>If the copy is in the backward direction (Xn holds a positive number), then:</para>
            <list type="unordered">
              <listitem>
                <content>Xn holds the number of bytes remaining to be copied.</content>
              </listitem>
              <listitem>
                <content>Xs holds the highest address to be copied from + 1 - Xn.</content>
              </listitem>
              <listitem>
                <content>Xd holds the highest address to be copied to + 1 - Xn.</content>
              </listitem>
            </list>
          </content>
        </listitem>
        <listitem>
          <content>
            <para>On completion of the instruction:</para>
            <list type="unordered">
              <listitem>
                <content>Xn holds 0.</content>
              </listitem>
              <listitem>
                <content>Xs holds an <arm-defined-word>IMPLEMENTATION SPECIFIC</arm-defined-word> value in the range with bounds:<list type="unordered">
                    <listitem>
                      <content>The lowest address that has been copied from.</content>
                    </listitem>
                    <listitem>
                      <content>The highest address that has been copied from + 1.</content>
                    </listitem>
                  </list>
                </content>
              </listitem>
              <listitem>
                <content>Xd holds an <arm-defined-word>IMPLEMENTATION SPECIFIC</arm-defined-word> value in the range with bounds:<list type="unordered">
                    <listitem>
                      <content>The lowest address that has been copied to.</content>
                    </listitem>
                    <listitem>
                      <content>The highest address that has not been copied to + 1.</content>
                    </listitem>
                  </list>
                </content>
              </listitem>
            </list>
          </content>
        </listitem>
      </list>
      <para>For CPYETRN, option B, when PSTATE.C = 1:</para>
      <list type="unordered">
        <listitem>
          <content>Xn holds the number of bytes remaining to be copied.</content>
        </listitem>
        <listitem>
          <content>If the copy is in the forward direction (PSTATE.N == 0), then:<list type="unordered">
              <listitem>
                <content>Xs holds the lowest address to be copied from.</content>
              </listitem>
              <listitem>
                <content>Xd holds the lowest address to be copied to.</content>
              </listitem>
            </list>
          </content>
        </listitem>
        <listitem>
          <content>
            <para>If the copy is in the backward direction (PSTATE.N == 1), then:</para>
            <list type="unordered">
              <listitem>
                <content>Xs holds the highest address to be copied from + 1.</content>
              </listitem>
              <listitem>
                <content>Xd holds the highest address to be copied to + 1.</content>
              </listitem>
            </list>
          </content>
        </listitem>
        <listitem>
          <content>
            <para>On completion of the instruction:</para>
            <list type="unordered">
              <listitem>
                <content>Xn holds 0.</content>
              </listitem>
              <listitem>
                <content>Xs holds an <arm-defined-word>IMPLEMENTATION SPECIFIC</arm-defined-word> value in the range with bounds:<list type="unordered">
                    <listitem>
                      <content>The lowest address that has been copied from.</content>
                    </listitem>
                    <listitem>
                      <content>The highest address that has been copied from + 1.</content>
                    </listitem>
                  </list>
                </content>
              </listitem>
              <listitem>
                <content>Xd holds an <arm-defined-word>IMPLEMENTATION SPECIFIC</arm-defined-word> value in the range with bounds:<list type="unordered">
                    <listitem>
                      <content>The lowest address that has been copied to.</content>
                    </listitem>
                    <listitem>
                      <content>The highest address that has not been copied to + 1.</content>
                    </listitem>
                  </list>
                </content>
              </listitem>
            </list>
          </content>
        </listitem>
      </list>
      <para>Explicit Memory  effects produced by the instruction behave as if the instruction was
  executed at EL0 if the <xref linkend="ARMARM_Effective_value">Effective value</xref> of
  PSTATE.UAO is 0 and either:</para>
      <list type="unordered">
        <listitem>
          <content>The instruction is executed at EL1.</content>
        </listitem>
        <listitem>
          <content>The instruction is executed at EL2 when the <xref linkend="ARMARM_Effective_value">Effective value</xref>
  of <register_link id="AArch64-hcr_el2.xml" state="AArch64">HCR_EL2()</register_link>.{E2H, TGE} is '11'.</content>
        </listitem>
      </list>
      <para>Otherwise, the Explicit Memory  effects operate with the restrictions determined by
  the Exception level at which the instruction is executed.</para>
    </authored>
    <encodingnotes>
      <para>For information about the <arm-defined-word>CONSTRAINED UNPREDICTABLE</arm-defined-word> behavior of this instruction, see <xref linkend="CJAEGDJC">Architectural Constraints on UNPREDICTABLE behaviors</xref>, and particularly <xref linkend="CEGCIDDEI6">Memory Copy and Memory Set CPY*</xref> and <xref linkend="ARMARM_CEGCCGAE">Crossing a page boundary with different memory types or Shareability attributes</xref>.</para>
    </encodingnotes>
  </desc>
  <alias_list howmany="0"/>
  <classes>
    <iclass name="Integer" oneof="1" id="iclass_integer" no_encodings="3" isa="A64">
      <docvars>
        <docvar key="instr-class" value="general"/>
        <docvar key="isa" value="A64"/>
      </docvars>
      <iclassintro count="3"/>
      <arch_variants>
        <arch_variant feature="FEAT_MOPS" name="v8Ap8"/>
      </arch_variants>
      <regdiagram form="32" psname="A64.ldst.memcms.CPYPTRN_CPY_memcms" tworows="1">
        <box hibit="31" width="2" name="sz" usename="1">
          <c colspan="2"/>
        </box>
        <box hibit="29" width="3" settings="3">
          <c>0</c>
          <c>1</c>
          <c>1</c>
        </box>
        <box hibit="26" name="o0" usename="1" settings="1" psbits="x">
          <c>1</c>
        </box>
        <box hibit="25" width="2" settings="2">
          <c>0</c>
          <c>1</c>
        </box>
        <box hibit="23" width="2" name="op1" usename="1">
          <c colspan="2"/>
        </box>
        <box hibit="21" width="1" settings="1">
          <c>0</c>
        </box>
        <box hibit="20" width="5" name="Rs" usename="1">
          <c colspan="5"/>
        </box>
        <box hibit="15" width="4" name="op2" usename="1" settings="4" psbits="xxxx">
          <c>1</c>
          <c>0</c>
          <c>1</c>
          <c>1</c>
        </box>
        <box hibit="11" width="2" settings="2">
          <c>0</c>
          <c>1</c>
        </box>
        <box hibit="9" width="5" name="Rn" usename="1">
          <c colspan="5"/>
        </box>
        <box hibit="4" width="5" name="Rd" usename="1">
          <c colspan="5"/>
        </box>
      </regdiagram>
      <encoding name="CPYPTRN_CPY_memcms" oneofinclass="3" oneof="3" label="Prologue" bitdiffs="op1 == 00">
        <docvars>
          <docvar key="instr-class" value="general"/>
          <docvar key="isa" value="A64"/>
          <docvar key="pme" value="pme-prologue"/>
          <docvar key="mnemonic" value="CPYPTRN"/>
        </docvars>
        <box hibit="23" width="2" name="op1">
          <c>0</c>
          <c>0</c>
        </box>
        <asmtemplate><text>CPYPTRN  [</text><a hover="For the &quot;Prologue&quot; variant: is the 64-bit name of the general-purpose register that holds the destination address and is updated by the instruction, encoded in the &quot;Rd&quot; field." link="XdOrXZR">&lt;Xd&gt;</a><text>]!, [</text><a hover="For the &quot;Prologue&quot; variant: is the 64-bit name of the general-purpose register that holds the source address and is updated by the instruction, encoded in the &quot;Rs&quot; field." link="XsOrXZR__5">&lt;Xs&gt;</a><text>]!, </text><a hover="For the &quot;Prologue&quot; variant: is the 64-bit name of the general-purpose register that holds the number of bytes to be transferred and is updated by the instruction to encode the remaining size and destination, encoded in the &quot;Rn&quot; field." link="XnOrXZR__2">&lt;Xn&gt;</a><text>!</text></asmtemplate>
      </encoding>
      <encoding name="CPYMTRN_CPY_memcms" oneofinclass="3" oneof="3" label="Main" bitdiffs="op1 == 01">
        <docvars>
          <docvar key="instr-class" value="general"/>
          <docvar key="isa" value="A64"/>
          <docvar key="pme" value="pme-main"/>
          <docvar key="mnemonic" value="CPYMTRN"/>
        </docvars>
        <box hibit="23" width="2" name="op1">
          <c>0</c>
          <c>1</c>
        </box>
        <asmtemplate><text>CPYMTRN  [</text><a hover="For the &quot;Epilogue&quot; and &quot;Main&quot; variants: is the 64-bit name of the general-purpose register that holds an encoding of the destination address, encoded in the &quot;Rd&quot; field." link="XdOrXZR__2">&lt;Xd&gt;</a><text>]!, [</text><a hover="For the &quot;Epilogue&quot; and &quot;Main&quot; variants: is the 64-bit name of the general-purpose register that holds an encoding of the source address, encoded in the &quot;Rs&quot; field." link="XsOrXZR__6">&lt;Xs&gt;</a><text>]!, </text><a hover="For the &quot;Main&quot; variant: is the 64-bit name of the general-purpose register that holds an encoding of the number of bytes to be transferred, encoded in the &quot;Rn&quot; field." link="XnOrXZR__3">&lt;Xn&gt;</a><text>!</text></asmtemplate>
      </encoding>
      <encoding name="CPYETRN_CPY_memcms" oneofinclass="3" oneof="3" label="Epilogue" bitdiffs="op1 == 10">
        <docvars>
          <docvar key="instr-class" value="general"/>
          <docvar key="isa" value="A64"/>
          <docvar key="pme" value="pme-epilogue"/>
          <docvar key="mnemonic" value="CPYETRN"/>
        </docvars>
        <box hibit="23" width="2" name="op1">
          <c>1</c>
          <c>0</c>
        </box>
        <asmtemplate><text>CPYETRN  [</text><a hover="For the &quot;Epilogue&quot; and &quot;Main&quot; variants: is the 64-bit name of the general-purpose register that holds an encoding of the destination address, encoded in the &quot;Rd&quot; field." link="XdOrXZR__2">&lt;Xd&gt;</a><text>]!, [</text><a hover="For the &quot;Epilogue&quot; and &quot;Main&quot; variants: is the 64-bit name of the general-purpose register that holds an encoding of the source address, encoded in the &quot;Rs&quot; field." link="XsOrXZR__6">&lt;Xs&gt;</a><text>]!, </text><a hover="For the &quot;Epilogue&quot; variant: is the 64-bit name of the general-purpose register that holds an encoding of the number of bytes to be transferred and is set to zero on completion of the instruction, encoded in the &quot;Rn&quot; field." link="XnOrXZR__4">&lt;Xn&gt;</a><text>!</text></asmtemplate>
      </encoding>
      <ps_section howmany="1">
        <ps name="A64.ldst.memcms.CPYPTRN_CPY_memcms" sections="1" secttype="noheading">
          <pstext mayhavelinks="1" section="Decode" rep_section="decode">if !IsFeatureImplemented(FEAT_MOPS) || sz != '00' then <a link="func_EndOfDecode_1" file="shared_pseudocode.xml">EndOfDecode</a>(<a link="enum_Decode_UNDEF" file="shared_pseudocode.xml">Decode_UNDEF</a>); end;

var memcpy : <a link="type_CPYParams" file="shared_pseudocode.xml">CPYParams</a>;
memcpy.d = UInt(Rd);
memcpy.s = UInt(Rs);
memcpy.n = UInt(Rn);
let options : bits(4) = op2;
let rnontemporal : boolean = options[3] == '1';
let wnontemporal : boolean = options[2] == '1';
case op1 of
    when '00' =&gt; memcpy.stage = <a link="enum_MOPSStage_Prologue" file="shared_pseudocode.xml">MOPSStage_Prologue</a>;
    when '01' =&gt; memcpy.stage = <a link="enum_MOPSStage_Main" file="shared_pseudocode.xml">MOPSStage_Main</a>;
    when '10' =&gt; memcpy.stage = <a link="enum_MOPSStage_Epilogue" file="shared_pseudocode.xml">MOPSStage_Epilogue</a>;
end;</pstext></ps>
      </ps_section>
    </iclass>
  </classes>
  <explanations scope="all">
    <explanation enclist="CPYPTRN_CPY_memcms" symboldefcount="1">
      <symbol link="XdOrXZR">&lt;Xd&gt;</symbol>
      <account encodedin="Rd">
        <intro>
          <para>For the &quot;Prologue&quot; variant: is the 64-bit name of the general-purpose register that holds the destination address and is updated by the instruction, encoded in the &quot;Rd&quot; field.</para>
        </intro>
      </account>
    </explanation>
    <explanation enclist="CPYMTRN_CPY_memcms, CPYETRN_CPY_memcms" symboldefcount="2">
      <symbol link="XdOrXZR__2">&lt;Xd&gt;</symbol>
      <account encodedin="Rd">
        <intro>
          <para>For the &quot;Epilogue&quot; and &quot;Main&quot; variants: is the 64-bit name of the general-purpose register that holds an encoding of the destination address, encoded in the &quot;Rd&quot; field.</para>
        </intro>
      </account>
    </explanation>
    <explanation enclist="CPYPTRN_CPY_memcms" symboldefcount="1">
      <symbol link="XsOrXZR__5">&lt;Xs&gt;</symbol>
      <account encodedin="Rs">
        <intro>
          <para>For the &quot;Prologue&quot; variant: is the 64-bit name of the general-purpose register that holds the source address and is updated by the instruction, encoded in the &quot;Rs&quot; field.</para>
        </intro>
      </account>
    </explanation>
    <explanation enclist="CPYMTRN_CPY_memcms, CPYETRN_CPY_memcms" symboldefcount="2">
      <symbol link="XsOrXZR__6">&lt;Xs&gt;</symbol>
      <account encodedin="Rs">
        <intro>
          <para>For the &quot;Epilogue&quot; and &quot;Main&quot; variants: is the 64-bit name of the general-purpose register that holds an encoding of the source address, encoded in the &quot;Rs&quot; field.</para>
        </intro>
      </account>
    </explanation>
    <explanation enclist="CPYPTRN_CPY_memcms" symboldefcount="1">
      <symbol link="XnOrXZR__2">&lt;Xn&gt;</symbol>
      <account encodedin="Rn">
        <intro>
          <para>For the &quot;Prologue&quot; variant: is the 64-bit name of the general-purpose register that holds the number of bytes to be transferred and is updated by the instruction to encode the remaining size and destination, encoded in the &quot;Rn&quot; field.</para>
        </intro>
      </account>
    </explanation>
    <explanation enclist="CPYMTRN_CPY_memcms" symboldefcount="2">
      <symbol link="XnOrXZR__3">&lt;Xn&gt;</symbol>
      <account encodedin="Rn">
        <intro>
          <para>For the &quot;Main&quot; variant: is the 64-bit name of the general-purpose register that holds an encoding of the number of bytes to be transferred, encoded in the &quot;Rn&quot; field.</para>
        </intro>
      </account>
    </explanation>
    <explanation enclist="CPYETRN_CPY_memcms" symboldefcount="3">
      <symbol link="XnOrXZR__4">&lt;Xn&gt;</symbol>
      <account encodedin="Rn">
        <intro>
          <para>For the &quot;Epilogue&quot; variant: is the 64-bit name of the general-purpose register that holds an encoding of the number of bytes to be transferred and is set to zero on completion of the instruction, encoded in the &quot;Rn&quot; field.</para>
        </intro>
      </account>
    </explanation>
  </explanations>
  <ps_section howmany="1">
    <ps name="A64.ldst.memcms.CPYPTRN_CPY_memcms" sections="1" secttype="Operation">
      <pstext mayhavelinks="1" section="Execute" rep_section="execute"><a link="func_CheckMOPSEnabled_0" file="shared_pseudocode.xml">CheckMOPSEnabled</a>();

<a link="func_CheckCPYConstrainedUnpredictable_3" file="shared_pseudocode.xml">CheckCPYConstrainedUnpredictable</a>(memcpy.n, memcpy.d, memcpy.s);

memcpy.nzcv        = <a link="global_PSTATE" file="shared_pseudocode.xml">PSTATE</a>.[N,Z,C,V];
memcpy.toaddress   = <a link="accessor_X_2" file="shared_pseudocode.xml">X</a>{64}(memcpy.d);
memcpy.fromaddress = <a link="accessor_X_2" file="shared_pseudocode.xml">X</a>{64}(memcpy.s);

if memcpy.stage == <a link="enum_MOPSStage_Prologue" file="shared_pseudocode.xml">MOPSStage_Prologue</a> then
    memcpy.cpysize = UInt(<a link="accessor_X_2" file="shared_pseudocode.xml">X</a>{64}(memcpy.n));
else
    memcpy.cpysize = SInt(<a link="accessor_X_2" file="shared_pseudocode.xml">X</a>{64}(memcpy.n));
end;

memcpy.implements_option_a = <a link="func_CPYOptionA_0" file="shared_pseudocode.xml">CPYOptionA</a>();

let rprivileged : boolean = (if options[1] == '1' then <a link="func_AArch64_IsUnprivAccessPriv_0" file="shared_pseudocode.xml">AArch64_IsUnprivAccessPriv</a>()
                                else <a link="global_PSTATE" file="shared_pseudocode.xml">PSTATE</a>.EL != <a link="global_EL0" file="shared_pseudocode.xml">EL0</a>);
let wprivileged : boolean = (if options[0] == '1' then <a link="func_AArch64_IsUnprivAccessPriv_0" file="shared_pseudocode.xml">AArch64_IsUnprivAccessPriv</a>()
                                else <a link="global_PSTATE" file="shared_pseudocode.xml">PSTATE</a>.EL != <a link="global_EL0" file="shared_pseudocode.xml">EL0</a>);

let raccdesc : <a link="type_AccessDescriptor" file="shared_pseudocode.xml">AccessDescriptor</a> = <a link="func_CreateAccDescMOPS_3" file="shared_pseudocode.xml">CreateAccDescMOPS</a>(<a link="enum_MemOp_LOAD" file="shared_pseudocode.xml">MemOp_LOAD</a>,  rprivileged, rnontemporal);
let waccdesc : <a link="type_AccessDescriptor" file="shared_pseudocode.xml">AccessDescriptor</a> = <a link="func_CreateAccDescMOPS_3" file="shared_pseudocode.xml">CreateAccDescMOPS</a>(<a link="enum_MemOp_STORE" file="shared_pseudocode.xml">MemOp_STORE</a>, wprivileged, wnontemporal);

if memcpy.stage == <a link="enum_MOPSStage_Prologue" file="shared_pseudocode.xml">MOPSStage_Prologue</a> then
    if memcpy.cpysize &gt; <a link="global_ArchMaxMOPSCPYSize" file="shared_pseudocode.xml">ArchMaxMOPSCPYSize</a> then
        memcpy.cpysize = <a link="global_ArchMaxMOPSCPYSize" file="shared_pseudocode.xml">ArchMaxMOPSCPYSize</a>;
    end;

    memcpy.forward = <a link="func_IsMemCpyForward_1" file="shared_pseudocode.xml">IsMemCpyForward</a>(memcpy);

    if memcpy.implements_option_a then
        memcpy.nzcv = '0000';
        if memcpy.forward then
            // Copy in the forward direction offsets the arguments.
            memcpy.toaddress   = memcpy.toaddress   + memcpy.cpysize;
            memcpy.fromaddress = memcpy.fromaddress + memcpy.cpysize;
            memcpy.cpysize     = 0 - memcpy.cpysize;
        end;
    else
        if !memcpy.forward then
            // Copy in the reverse direction offsets the arguments.
            memcpy.toaddress   = memcpy.toaddress   + memcpy.cpysize;
            memcpy.fromaddress = memcpy.fromaddress + memcpy.cpysize;
            memcpy.nzcv = '1010';
        else
            memcpy.nzcv = '0010';
        end;
    end;
end;

memcpy.stagecpysize = <a link="func_MemCpyStageSize_1" file="shared_pseudocode.xml">MemCpyStageSize</a>(memcpy);

if memcpy.stage != <a link="enum_MOPSStage_Prologue" file="shared_pseudocode.xml">MOPSStage_Prologue</a> then
    memcpy.forward = memcpy.cpysize &lt; 0 || (!memcpy.implements_option_a &amp;&amp; memcpy.nzcv[3] == '0');
    <a link="func_CheckMemCpyParams_2" file="shared_pseudocode.xml">CheckMemCpyParams</a>(memcpy, options);
end;

var copied : integer;
var iswrite : boolean;
var memaddrdesc : <a link="type_AddressDescriptor" file="shared_pseudocode.xml">AddressDescriptor</a>;
var memstatus : <a link="type_PhysMemRetStatus" file="shared_pseudocode.xml">PhysMemRetStatus</a>;
var fault : boolean = FALSE;
var B : <a link="type_MOPSBlockSize" file="shared_pseudocode.xml">MOPSBlockSize</a> = 0;

if memcpy.implements_option_a then
    while memcpy.stagecpysize != 0 &amp;&amp; !fault looplimit <a link="global_ArchMaxMOPSCPYSize" file="shared_pseudocode.xml">ArchMaxMOPSCPYSize</a> do
        // IMP DEF selection of the block size that is worked on. While many
        // implementations might make this constant, that is not assumed.
        B = <a link="func_CPYSizeChoice_1" file="shared_pseudocode.xml">CPYSizeChoice</a>(memcpy);

        if memcpy.forward then
            assert B &lt;= -1 * memcpy.stagecpysize;
            (copied, iswrite, memaddrdesc, memstatus) = <a link="func_MemCpyBytes_6" file="shared_pseudocode.xml">MemCpyBytes</a>(
                                                                memcpy.toaddress + memcpy.cpysize,
                                                                memcpy.fromaddress + memcpy.cpysize,
                                                                memcpy.forward, B,
                                                                raccdesc, waccdesc);
            if copied != B then
                fault = TRUE;
            else
                memcpy.cpysize      = memcpy.cpysize      + B;
                memcpy.stagecpysize = memcpy.stagecpysize + B;
            end;

        else
            assert B &lt;= memcpy.stagecpysize;
            memcpy.cpysize      = memcpy.cpysize      - B;
            memcpy.stagecpysize = memcpy.stagecpysize - B;

            (copied, iswrite, memaddrdesc, memstatus) = <a link="func_MemCpyBytes_6" file="shared_pseudocode.xml">MemCpyBytes</a>(
                                                                memcpy.toaddress   + memcpy.cpysize,
                                                                memcpy.fromaddress + memcpy.cpysize,
                                                                memcpy.forward, B, raccdesc,
                                                                waccdesc);
            if copied != B then
                fault               = TRUE;
                memcpy.cpysize      = memcpy.cpysize      + B;
                memcpy.stagecpysize = memcpy.stagecpysize + B;
            end;
        end;
    end;

else
    while memcpy.stagecpysize &gt; 0 &amp;&amp; !fault looplimit <a link="global_ArchMaxMOPSCPYSize" file="shared_pseudocode.xml">ArchMaxMOPSCPYSize</a> do
        // IMP DEF selection of the block size that is worked on. While many
        // implementations might make this constant, that is not assumed.
        B = <a link="func_CPYSizeChoice_1" file="shared_pseudocode.xml">CPYSizeChoice</a>(memcpy);
        assert B &lt;= memcpy.stagecpysize;

        if memcpy.forward then
            (copied, iswrite, memaddrdesc, memstatus) = <a link="func_MemCpyBytes_6" file="shared_pseudocode.xml">MemCpyBytes</a>(memcpy.toaddress,
                                                                    memcpy.fromaddress,
                                                                    memcpy.forward, B,
                                                                    raccdesc, waccdesc);
            if copied != B then
                fault = TRUE;
            else
                memcpy.fromaddress = memcpy.fromaddress + B;
                memcpy.toaddress   = memcpy.toaddress   + B;
            end;
        else
            (copied, iswrite, memaddrdesc, memstatus) = <a link="func_MemCpyBytes_6" file="shared_pseudocode.xml">MemCpyBytes</a>(memcpy.toaddress   - B,
                                                                    memcpy.fromaddress - B,
                                                                    memcpy.forward, B,
                                                                    raccdesc, waccdesc);

            if copied != B then
                fault = TRUE;
            else
                memcpy.fromaddress = memcpy.fromaddress - B;
                memcpy.toaddress   = memcpy.toaddress   - B;
            end;
        end;

        if !fault then
            memcpy.cpysize      = memcpy.cpysize        - B;
            memcpy.stagecpysize = memcpy.stagecpysize   - B;
        end;
    end;
end;

<a link="func_UpdateCpyRegisters_3" file="shared_pseudocode.xml">UpdateCpyRegisters</a>(memcpy, fault, copied);

if fault then
    if <a link="func_IsFault_1" file="shared_pseudocode.xml">IsFault</a>(memaddrdesc) then
        <a link="func_AArch64_Abort_1" file="shared_pseudocode.xml">AArch64_Abort</a>(memaddrdesc.fault);
    else
        let accdesc : <a link="type_AccessDescriptor" file="shared_pseudocode.xml">AccessDescriptor</a> = if iswrite then waccdesc else raccdesc;
        <a link="func_HandleExternalAbort_5" file="shared_pseudocode.xml">HandleExternalAbort</a>(memstatus, iswrite, memaddrdesc, B, accdesc);
    end;
end;

if memcpy.stage == <a link="enum_MOPSStage_Prologue" file="shared_pseudocode.xml">MOPSStage_Prologue</a> then
    PSTATE.[N,Z,C,V] = memcpy.nzcv;
end;</pstext></ps>
  </ps_section>
  <timestamp>2026-03-26 20:27:25</timestamp>
  <commit_id>2026-03_rel</commit_id>
</instructionsection>