BL/BLX (Thumb) 机器码计算规则,从LLVM里挖出来的


#1
static int32_t arm_thumb_bl(int32_t immediate)
{
    // The value doesn't encode the low bit (always zero) and is offset by
    // four. The 32-bit immediate value is encoded as
    //   imm32 = SignExtend(S:I1:I2:imm10:imm11:0)
    // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S).
    // The value is encoded into disjoint bit positions in the destination
    // opcode. x = unchanged, I = immediate value bit, S = sign extension bit,
    // J = either J1 or J2 bit
    //
    //   BL:  xxxxxSIIIIIIIIII xxJxJIIIIIIIIIII 0xF000D000
    //
    // Note that the halfwords are stored high first, low second; so we need
    // to transpose the fixup value here to map properly.
    uint32_t offset = (immediate - 4) >> 1;
    uint32_t S = (offset & 0x800000) >> 23;
    uint32_t I1 = (offset & 0x400000) >> 22;
    uint32_t J1 = (I1 ^ 0x1) ^ S;
    uint32_t I2 = (offset & 0x200000) >> 21;
    uint32_t J2 = (I2 ^ 0x1) ^ S;
    uint32_t imm10 = (offset & 0x1FF800) >> 11;
    uint32_t imm11 = (offset & 0x000007FF);

    uint32_t Binary = 0;
    uint32_t firstHalf = (((uint16_t)S << 10) | (uint16_t)imm10);
    uint32_t secondHalf = (((uint16_t)J1 << 13) | ((uint16_t)J2 << 11) | (uint16_t)imm11);
    Binary |= secondHalf;
    Binary |= firstHalf << 16;
    Binary |= 0xF000D000;

    uint32_t Byte0 = (Binary & 0xFF000000) >> 8;
    uint32_t Byte1 = (Binary & 0x00FF0000) << 8;
    uint32_t Byte2 = (Binary & 0x0000FF00) >> 8;
    uint32_t Byte3 = (Binary & 0x000000FF) << 8;

    Binary = Byte0 | Byte1 | Byte2 | Byte3;
    return Binary;
}

static int32_t arm_thumb_blx(int32_t immediate)
{
    // The value doesn't encode the low two bits (always zero) and is offset by
     // four (see fixup_arm_thumb_cp). The 32-bit immediate value is encoded as
     //   imm32 = SignExtend(S:I1:I2:imm10H:imm10L:00)
     // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S).
     // The value is encoded into disjoint bit positions in the destination
     // opcode. x = unchanged, I = immediate value bit, S = sign extension bit,
     // J = either J1 or J2 bit, 0 = zero.
     //
     //   BLX: xxxxxSIIIIIIIIII xxJxJIIIIIIIIII0
     //
     // Note that the halfwords are stored high first, low second; so we need
     // to transpose the fixup value here to map properly.
    uint32_t offset = (immediate - 2) >> 2;
    uint32_t signBit = (offset & 0x400000) >> 22;
    uint32_t I1Bit = (offset & 0x200000) >> 21;
    uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit;
    uint32_t I2Bit = (offset & 0x100000) >> 20;
    uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;
    uint32_t imm10HBits = (offset & 0xFFC00) >> 10;
    uint32_t imm10LBits = (offset & 0x3FF);

    uint32_t Binary = 0;
    uint32_t firstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10HBits);
    uint32_t secondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) | ((uint16_t)imm10LBits) << 1);
    Binary |= secondHalf;
    Binary |= firstHalf << 16;
    Binary |= 0xF000C000;

    uint32_t Byte0 = (Binary & 0xFF000000) >> 8;
    uint32_t Byte1 = (Binary & 0x00FF0000) << 8;
    uint32_t Byte2 = (Binary & 0x0000FF00) >> 8;
    uint32_t Byte3 = (Binary & 0x000000FF) << 8;

    Binary = Byte0 | Byte1 | Byte2 | Byte3;
    return Binary;
}

#2

赞. 不知道是否可以表明下路径.


#3

应该是CodeGen里