You can get this from the ARM manual; for example from the version linked at the link you found, https://ece.uwaterloo.ca/~ece222/ARM/ARM7-TDMI-manual-pt3.pdf.
First, a quick calculation
8FE82, so you see you have more than 12 bits, and need to use the long branch format in 5.19, which splits your
BL into two instructions. The section says "The branch offset must take account of the prefetch operation, which causes the PC to be 1 word (4 bytes) ahead of the current instruction", so the offset you need is from 4 bytes behind
52F4DA, which means the offset for the instructions - the value you want to add to
The first part of the instruction shifts its partial offset left by 12 bits, and adds this to PC. The instruction format is
1111HXXXXXXXXXXX in binary, with
F000+XXXX in hex. What you want to add to PC in this step is
8F000, so the opcode for this instruction is
The second part shifts its partial offset left by one bit (remember thumb instructions are aligned to 16 bit, so the last bit of an offset is always 0, so it doesn't have to be represented in the hex opcode), and it has
H=1, so the opcode is
F800+XXXX. What you want to add in this step is
E7E. Shift that right by one bit to get
73f, and add to your opcode to get
So, your BL instruction is
To confirm this, create an assembly program, assemble it, and check the result:
arm-linux-gnueabi-as -o y.o y.s
arm-linux-gnueabi-objdump -s y.o | grep -v "00000000 00000000 00000000 00000000"
52f4d0 00000000 00008ff0 3fff0000 00000000 ........?.......
Remember words are byte-swapped due to little-endianness, and you'll find your
F08F FF3F opcode there.
EDIT: I just fixed the address of the second .org since it seemed miss-typed just to avoid confusion. Now it looks consistent I think :)