Search code examples
qemuthumb

QEMU Branch and Exchange (arm thumb) instruction doesn't get called


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?


Solution

  • 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.