So Im testing a change in an arm simulator with a QEMU backend and My microbenchmarks are not getting triggered for the Branch and Exchange instruction.
particular chunk I care about: https://github.com/qemu/qemu/blob/19b599f7664b2ebfd0f405fb79c14dd241557452/target/arm/translate.c#L11748
anyways I figured I'd check the bits by hand first
so:
insn = (0b010001 << 10)
will equal: 100010000000000
so if that were to hit the switch statement:
switch (insn >> 12)
we would get: 4. All good so far.
We first check if (insn & (1 << 11))
thats 0 still good we go on to the next conditional
if (insn & (1 << 10))
returns 1024 so we take the branch.
Here is where things start to get hairy.
we do
op = (insn >> 8) & 3;
switch (op)
the branch exchange code is in case 3
but (0b100010000000000 >> 8) & 3
will be 0:
to make it more clear 0b1000100 & 0b11
does not line up at all.
What am I missing here? Is this a bug?
0100010000000000 (ie 0b010001 << 10) is not a Thumb BX instruction, which is why if you feed it into the decoder it won't go down the code path for BX. As the comment in the code says, the BX and BLX insns are 0b0100_0111_xxxx_xxxx. 0100010000000000 is a register-register ADD instruction.
You can confirm this by looking at the v7A Arm ARM (DDI0406C.c, available at https://developer.arm.com/docs/ddi0406/c/arm-architecture-reference-manual-armv7-a-and-armv7-r-edition) and in particular the decode tables in section A6.2.