<?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-2025 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="BL_i" title="BL, BLX (immediate) -- AArch32" type="instruction">
  <docvars>
    <docvar key="instr-class" value="general"/>
  </docvars>
  <heading>BL, BLX (immediate)</heading>
  <desc>
    <brief>
      <para>Branch with Link and optional Exchange (immediate)</para>
    </brief>
    <authored>
      <para>Branch with Link calls a subroutine at a PC-relative address,
and setting LR to the return address.</para>
      <para>Branch with Link and Exchange Instruction Sets (immediate)
calls a subroutine at a PC-relative address, setting LR to
the return address, and changes the instruction
set from A32 to T32, or from T32 to A32.</para>
    </authored>
    <encodingnotes>
      <para>For more information about the <arm-defined-word>CONSTRAINED UNPREDICTABLE</arm-defined-word> behavior, see <xref linkend="ARMARM_CJAEGDJC">Architectural Constraints on UNPREDICTABLE behaviors</xref>.</para>
    </encodingnotes>
  </desc>
  <alias_list howmany="0"/>
  <classes>
    <classesintro count="4">
      <txt>It has encodings from the following instruction sets:</txt>
      <txt> A32 (</txt>
      <a href="#iclass_a1">A1</a>
      <txt> and </txt>
      <a href="#iclass_a2">A2</a>
      <txt>)</txt>
      <txt> and </txt>
      <txt> T32 (</txt>
      <a href="#iclass_t1">T1</a>
      <txt> and </txt>
      <a href="#iclass_t2">T2</a>
      <txt>)</txt>
      <txt>.</txt>
    </classesintro>
    <iclass name="A1" oneof="4" id="iclass_a1" no_encodings="1" isa="A32">
      <docvars>
        <docvar key="armarmheading" value="A1"/>
        <docvar key="instr-class" value="general"/>
        <docvar key="isa" value="A32"/>
        <docvar key="mnemonic" value="BL"/>
      </docvars>
      <iclassintro count="1"/>
      <regdiagram form="32" psname="A32.brblk.b_imm.BL_i_A1" tworows="1">
        <box hibit="31" width="4" name="cond" usename="1" settings="4" constraint="!= 1111">
          <c colspan="4">!= 1111</c>
        </box>
        <box hibit="27" width="2" settings="2">
          <c>1</c>
          <c>0</c>
        </box>
        <box hibit="25" width="1" settings="1">
          <c>1</c>
        </box>
        <box hibit="24" name="H" usename="1" settings="1" psbits="x">
          <c>1</c>
        </box>
        <box hibit="23" width="24" name="imm24" usename="1">
          <c colspan="24"/>
        </box>
      </regdiagram>
      <encoding name="BL_i_A1" oneofinclass="1" oneof="4" label="">
        <docvars>
          <docvar key="armarmheading" value="A1"/>
          <docvar key="instr-class" value="general"/>
          <docvar key="isa" value="A32"/>
          <docvar key="mnemonic" value="BL"/>
        </docvars>
        <asmtemplate><text>BL{</text><a hover="For the &quot;A1&quot; variant: see x[Standard assembler syntax fields](Babbefhf)." link="cond__3">&lt;c&gt;</a><text>}{</text><a hover="See x[Standard assembler syntax fields](Babbefhf)." link="qw_option">&lt;q&gt;</a><text>}  </text><a hover="For the &quot;A1&quot; variant: the label of the instruction that is to be branched to. The assembler calculates the required value of the offset from the PC value of the BL instruction to this label, then selects an encoding that sets imm32 to that offset." link="label__3">&lt;label&gt;</a></asmtemplate>
      </encoding>
      <ps_section howmany="1">
        <ps name="A32.brblk.b_imm.BL_i_A1" sections="1" secttype="noheading">
          <pstext mayhavelinks="1" section="Decode" rep_section="decode">let imm32 : bits(32) = SignExtend{}(imm24::'00');
let targetInstrSet : <a link="InstrSet" file="shared_pseudocode.xml" hover="type InstrSet">InstrSet</a> = InstrSet_A32;</pstext></ps>
      </ps_section>
    </iclass>
    <iclass name="A2" oneof="4" id="iclass_a2" no_encodings="1" isa="A32">
      <docvars>
        <docvar key="armarmheading" value="A2"/>
        <docvar key="instr-class" value="general"/>
        <docvar key="isa" value="A32"/>
        <docvar key="mnemonic" value="BLX"/>
      </docvars>
      <iclassintro count="1"/>
      <regdiagram form="32" psname="A32.brblk.b_imm.BL_i_A2">
        <box hibit="31" width="4" settings="4">
          <c>1</c>
          <c>1</c>
          <c>1</c>
          <c>1</c>
        </box>
        <box hibit="27" width="2" settings="2">
          <c>1</c>
          <c>0</c>
        </box>
        <box hibit="25" width="1" settings="1">
          <c>1</c>
        </box>
        <box hibit="24" width="1" name="H" usename="1">
          <c colspan="1"/>
        </box>
        <box hibit="23" width="24" name="imm24" usename="1">
          <c colspan="24"/>
        </box>
      </regdiagram>
      <encoding name="BL_i_A2" oneofinclass="1" oneof="4" label="">
        <docvars>
          <docvar key="armarmheading" value="A2"/>
          <docvar key="instr-class" value="general"/>
          <docvar key="isa" value="A32"/>
          <docvar key="mnemonic" value="BLX"/>
        </docvars>
        <asmtemplate><text>BLX{</text><a hover="For the &quot;A2&quot; variant: see x[Standard assembler syntax fields](Babbefhf). &lt;c&gt; must be AL or omitted." link="AL_option">&lt;c&gt;</a><text>}{</text><a hover="See x[Standard assembler syntax fields](Babbefhf)." link="qw_option">&lt;q&gt;</a><text>}  </text><a hover="For the &quot;A2&quot; variant: the label of the instruction that is to be branched to. The assembler calculates the required value of the offset from the PC value of the BLX instruction to this label, then selects an encoding with imm32 set to that offset." link="imm24_H">&lt;label&gt;</a></asmtemplate>
      </encoding>
      <ps_section howmany="1">
        <ps name="A32.brblk.b_imm.BL_i_A2" sections="1" secttype="noheading">
          <pstext mayhavelinks="1" section="Decode" rep_section="decode">let imm32 : bits(32) = SignExtend{}(imm24::H::'0');
let targetInstrSet : <a link="InstrSet" file="shared_pseudocode.xml" hover="type InstrSet">InstrSet</a> = InstrSet_T32;</pstext></ps>
      </ps_section>
    </iclass>
    <iclass name="T1" oneof="4" id="iclass_t1" no_encodings="1" isa="T32">
      <docvars>
        <docvar key="armarmheading" value="T1"/>
        <docvar key="instr-class" value="general"/>
        <docvar key="isa" value="T32"/>
        <docvar key="mnemonic" value="BL"/>
      </docvars>
      <iclassintro count="1"/>
      <regdiagram form="16x2" psname="T32.w.bcrtrl.bl.BL_i_T1">
        <box hibit="31" width="3" settings="3">
          <c>1</c>
          <c>1</c>
          <c>1</c>
        </box>
        <box hibit="28" width="2" settings="2">
          <c>1</c>
          <c>0</c>
        </box>
        <box hibit="26" width="1" name="S" usename="1">
          <c colspan="1"/>
        </box>
        <box hibit="25" width="10" name="imm10" usename="1">
          <c colspan="10"/>
        </box>
        <box hibit="15" width="1" settings="1">
          <c>1</c>
        </box>
        <box hibit="14" width="1" settings="1">
          <c>1</c>
        </box>
        <box hibit="13" width="1" name="J1" usename="1">
          <c colspan="1"/>
        </box>
        <box hibit="12" width="1" settings="1">
          <c>1</c>
        </box>
        <box hibit="11" width="1" name="J2" usename="1">
          <c colspan="1"/>
        </box>
        <box hibit="10" width="11" name="imm11" usename="1">
          <c colspan="11"/>
        </box>
      </regdiagram>
      <encoding name="BL_i_T1" oneofinclass="1" oneof="4" label="">
        <docvars>
          <docvar key="armarmheading" value="T1"/>
          <docvar key="instr-class" value="general"/>
          <docvar key="isa" value="T32"/>
          <docvar key="mnemonic" value="BL"/>
        </docvars>
        <asmtemplate><text>BL{</text><a hover="For the &quot;T1&quot; and &quot;T2&quot; variants: see x[Standard assembler syntax fields](Babbefhf)." link="AL_option__6">&lt;c&gt;</a><text>}{</text><a hover="See x[Standard assembler syntax fields](Babbefhf)." link="qw_option">&lt;q&gt;</a><text>}  </text><a hover="For the &quot;T1&quot; variant: the label of the instruction that is to be branched to." link="label__6">&lt;label&gt;</a></asmtemplate>
      </encoding>
      <ps_section howmany="1">
        <ps name="T32.w.bcrtrl.bl.BL_i_T1" sections="1" secttype="noheading">
          <pstext mayhavelinks="1" section="Decode" rep_section="decode">let I1 : bit = NOT(J1 XOR S);
let I2 : bit = NOT(J2 XOR S);
let imm32 : bits(32) = SignExtend{}(S::I1::I2::imm10::imm11::'0');
let targetInstrSet : <a link="InstrSet" file="shared_pseudocode.xml" hover="type InstrSet">InstrSet</a> = InstrSet_T32;
if InITBlock() &amp;&amp; !LastInITBlock() then UnpredictableProcedure(); end;</pstext></ps>
      </ps_section>
    </iclass>
    <iclass name="T2" oneof="4" id="iclass_t2" no_encodings="1" isa="T32">
      <docvars>
        <docvar key="armarmheading" value="T2"/>
        <docvar key="instr-class" value="general"/>
        <docvar key="isa" value="T32"/>
        <docvar key="mnemonic" value="BLX"/>
      </docvars>
      <iclassintro count="1"/>
      <regdiagram form="16x2" psname="T32.w.bcrtrl.blx.BL_i_T2">
        <box hibit="31" width="3" settings="3">
          <c>1</c>
          <c>1</c>
          <c>1</c>
        </box>
        <box hibit="28" width="2" settings="2">
          <c>1</c>
          <c>0</c>
        </box>
        <box hibit="26" width="1" name="S" usename="1">
          <c colspan="1"/>
        </box>
        <box hibit="25" width="10" name="imm10H" usename="1">
          <c colspan="10"/>
        </box>
        <box hibit="15" width="1" settings="1">
          <c>1</c>
        </box>
        <box hibit="14" width="1" settings="1">
          <c>1</c>
        </box>
        <box hibit="13" width="1" name="J1" usename="1">
          <c colspan="1"/>
        </box>
        <box hibit="12" width="1" settings="1">
          <c>0</c>
        </box>
        <box hibit="11" width="1" name="J2" usename="1">
          <c colspan="1"/>
        </box>
        <box hibit="10" width="10" name="imm10L" usename="1">
          <c colspan="10"/>
        </box>
        <box hibit="0" width="1" name="H" usename="1">
          <c colspan="1"/>
        </box>
      </regdiagram>
      <encoding name="BL_i_T2" oneofinclass="1" oneof="4" label="">
        <docvars>
          <docvar key="armarmheading" value="T2"/>
          <docvar key="instr-class" value="general"/>
          <docvar key="isa" value="T32"/>
          <docvar key="mnemonic" value="BLX"/>
        </docvars>
        <asmtemplate><text>BLX{</text><a hover="For the &quot;T1&quot; and &quot;T2&quot; variants: see x[Standard assembler syntax fields](Babbefhf)." link="AL_option__6">&lt;c&gt;</a><text>}{</text><a hover="See x[Standard assembler syntax fields](Babbefhf)." link="qw_option">&lt;q&gt;</a><text>}  </text><a hover="For the &quot;T2&quot; variant: the label of the instruction that is to be branched to." link="label__7">&lt;label&gt;</a></asmtemplate>
      </encoding>
      <ps_section howmany="1">
        <ps name="T32.w.bcrtrl.blx.BL_i_T2" sections="1" secttype="noheading">
          <pstext mayhavelinks="1" section="Decode" rep_section="decode">if H == '1' then Undefined(); end;
let I1 : bit = NOT(J1 XOR S);
let I2 : bit = NOT(J2 XOR S);
let imm32 : bits(32) = SignExtend{}(S::I1::I2::imm10H::imm10L::'00');
let targetInstrSet : <a link="InstrSet" file="shared_pseudocode.xml" hover="type InstrSet">InstrSet</a> = InstrSet_A32;
if InITBlock() &amp;&amp; !LastInITBlock() then UnpredictableProcedure(); end;</pstext></ps>
      </ps_section>
    </iclass>
  </classes>
  <explanations scope="all">
    <explanation enclist="BL_i_A1" symboldefcount="1">
      <symbol link="cond__3">&lt;c&gt;</symbol>
      <account encodedin="cond">
        <intro>
          <para>For the "A1" variant: see <xref linkend="Babbefhf">Standard assembler syntax fields</xref>.</para>
        </intro>
      </account>
    </explanation>
    <explanation enclist="BL_i_A2" symboldefcount="2">
      <symbol link="AL_option">&lt;c&gt;</symbol>
      <account encodedin="">
        <intro>
          <para>For the "A2" variant: see <xref linkend="Babbefhf">Standard assembler syntax fields</xref>. <syntax>&lt;c&gt;</syntax> must be <value>AL</value> or omitted.</para>
        </intro>
      </account>
    </explanation>
    <explanation enclist="BL_i_T1, BL_i_T2" symboldefcount="3">
      <symbol link="AL_option__6">&lt;c&gt;</symbol>
      <account encodedin="">
        <intro>
          <para>For the "T1" and "T2" variants: see <xref linkend="Babbefhf">Standard assembler syntax fields</xref>.</para>
        </intro>
      </account>
    </explanation>
    <explanation enclist="BL_i_A1, BL_i_A2, BL_i_T1, BL_i_T2" symboldefcount="1">
      <symbol link="qw_option">&lt;q&gt;</symbol>
      <account encodedin="">
        <intro>
          <para>See <xref linkend="Babbefhf">Standard assembler syntax fields</xref>.</para>
        </intro>
      </account>
    </explanation>
    <explanation enclist="BL_i_A1" symboldefcount="1">
      <symbol link="label__3">&lt;label&gt;</symbol>
      <account encodedin="imm24">
        <intro>
          <para>For the "A1" variant: the label of the instruction that is to be branched to. The assembler calculates the required value of the offset from the PC value of the <instruction>BL</instruction> instruction to this label, then selects an encoding that sets <field>imm32</field> to that offset.</para>
          <para>Permitted offsets are multiples of 4 in the range –33554432 to 33554428.</para>
        </intro>
      </account>
    </explanation>
    <explanation enclist="BL_i_A2" symboldefcount="2">
      <symbol link="imm24_H">&lt;label&gt;</symbol>
      <account encodedin="(imm24 :: H)">
        <intro>
          <para>For the "A2" variant: the label of the instruction that is to be branched to. The assembler calculates the required value of the offset from the PC value of the <instruction>BLX</instruction> instruction to this label, then selects an encoding with <field>imm32</field> set to that offset.</para>
          <para>Permitted offsets are even numbers in the range –33554432 to 33554430.</para>
        </intro>
      </account>
    </explanation>
    <explanation enclist="BL_i_T1" symboldefcount="3">
      <symbol link="label__6">&lt;label&gt;</symbol>
      <account encodedin="(S :: NOT (J1 XOR S) :: NOT (J2 XOR S) :: imm10 :: imm11)">
        <intro>
          <para>For the "T1" variant: the label of the instruction that is to be branched to.</para>
          <para>The assembler calculates the required value of the offset from the PC value of the <instruction>BL</instruction> instruction to this label, then selects an encoding with <field>imm32</field> set to that offset.</para>
          <para>Permitted offsets are even numbers in the range –16777216 to 16777214.</para>
        </intro>
      </account>
    </explanation>
    <explanation enclist="BL_i_T2" symboldefcount="4">
      <symbol link="label__7">&lt;label&gt;</symbol>
      <account encodedin="(S :: NOT (J1 XOR S) :: NOT (J2 XOR S) :: imm10 :: imm11)">
        <intro>
          <para>For the "T2" variant: the label of the instruction that is to be branched to.</para>
          <para>The assembler calculates the required value of the offset from the <function>Align(PC, 4)</function> value of the <instruction>BLX</instruction> instruction to this label, then selects an encoding with <field>imm32</field> set to that offset.</para>
          <para>Permitted offsets are multiples of 4 in the range –16777216 to 16777212.</para>
        </intro>
      </account>
    </explanation>
  </explanations>
  <ps_section howmany="1">
    <ps name="A32.brblk.b_imm.BL_i_A1" sections="1" secttype="Operation">
      <pstext mayhavelinks="1" section="Execute" rep_section="execute">if ConditionPassed() then
    EncodingSpecificOperations();
    if CurrentInstrSet() == InstrSet_A32 then
        LR() = PC32() - 4;
    else
        LR() = PC32()[31:1] :: '1';
    end;
    var targetAddress : bits(32);
    if targetInstrSet == InstrSet_A32 then
        targetAddress = AlignDownSize(PC32(),4) + imm32;
    else
        targetAddress = PC32() + imm32;
    end;
    SelectInstrSet(targetInstrSet);
    BranchWritePC(targetAddress, BranchType_DIRCALL);
end;</pstext></ps>
  </ps_section>
  <timestamp>2026-03-12 12:23:09</timestamp>
  <commit_id>2025-09_rel_asl1</commit_id>
</instructionsection>
